From 1cfda206a8b59363a4ed99ad55dd4f97a84b2fd5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 16 Mar 2017 11:43:06 +0100 Subject: [PATCH 001/987] Merge #9993: Initialize nRelockTime fb6f90a Initialize nRelockTime (Patrick Strateman) Tree-SHA512: 82675ab4b05d5f3ea08a99e85d3f49d18068887d23cbacb5e899ad66799049c5f1d5bd33768dbe153116424c9f0caddaa3622000924e373aa01ac2a54b5f3577 --- src/wallet/wallet.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index fc5e95e05f67..26095893b95f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -803,6 +803,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface nLastResend = 0; nTimeFirstKey = 0; fBroadcastTransactions = false; + nRelockTime = 0; fAnonymizableTallyCached = false; fAnonymizableTallyCachedNonDenom = false; vecAnonymizableTallyCached.clear(); From 5ae202da9677882b9d9893605c25abc97fea8fd9 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 16 Mar 2017 11:57:09 +0100 Subject: [PATCH 002/987] Merge #9842: Fix RPC failure testing (continuation of #9707) c9bd0f6 Fix RPC failure testing (2 of 2) (John Newbery) Tree-SHA512: df30e6e85abe8c4e12910dc60699f1201e9c243457abd738c1fdeac45f0ff05c674f68619ad9a47c847ec557954007d672cd89d3a9a3b2398dd188d9ffa6dcc9 s/serialize_with_witness/serialize/ miss a tx_submit -> sendrawtransaction dropped dip4 Fix tests Signed-off-by: Pasta Fix file permissions --- qa/rpc-tests/bip65-cltv.py | 8 +--- qa/rpc-tests/bip68-sequence.py | 46 +++++++--------------- qa/rpc-tests/bipdersig.py | 8 +--- qa/rpc-tests/blockchain.py | 6 +-- qa/rpc-tests/disablewallet.py | 17 ++------ qa/rpc-tests/getblocktemplate_proposals.py | 4 +- qa/rpc-tests/keypool.py | 18 ++------- qa/rpc-tests/mempool_packages.py | 29 ++++++-------- qa/rpc-tests/mempool_reorg.py | 16 +++++--- qa/rpc-tests/mempool_spendcoinbase.py | 2 +- qa/rpc-tests/nulldummy.py | 29 +++++--------- qa/rpc-tests/prioritise_transaction.py | 10 ++--- qa/rpc-tests/rpcbind_test.py | 6 +-- qa/rpc-tests/wallet.py | 20 +++------- 14 files changed, 73 insertions(+), 146 deletions(-) diff --git a/qa/rpc-tests/bip65-cltv.py b/qa/rpc-tests/bip65-cltv.py index c9d02a98f3f4..7f13bb9952f1 100755 --- a/qa/rpc-tests/bip65-cltv.py +++ b/qa/rpc-tests/bip65-cltv.py @@ -69,12 +69,8 @@ def run_test(self): if (self.nodes[0].getblockcount() != cnt + 1051): raise AssertionError("Failed to mine a version=4 block") - # Mine 1 old-version blocks - try: - self.nodes[1].generate(1) - raise AssertionError("Succeeded to mine a version=3 block after 950 version=4 blocks") - except JSONRPCException: - pass + # Mine 1 old-version blocks. This should fail + assert_raises_jsonrpc(-1,"CreateNewBlock: TestBlockValidity failed: bad-version(0x00000003)", self.nodes[1].generate, 1) self.sync_all() if (self.nodes[0].getblockcount() != cnt + 1051): raise AssertionError("Accepted a version=3 block after 950 version=4 blocks") diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py index c6d11ac9a201..5a628a2fa0bf 100755 --- a/qa/rpc-tests/bip68-sequence.py +++ b/qa/rpc-tests/bip68-sequence.py @@ -90,12 +90,7 @@ def test_disable_flag(self): tx2.vout = [CTxOut(int(value-self.relayfee*COIN), CScript([b'a']))] tx2.rehash() - try: - self.nodes[0].sendrawtransaction(ToHex(tx2)) - except JSONRPCException as exp: - assert_equal(exp.error["message"], NOT_FINAL_ERROR) - else: - assert(False) + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx2)) # Setting the version back down to 1 should disable the sequence lock, # so this should be accepted. @@ -190,14 +185,12 @@ def test_sequence_lock_confirmed_inputs(self): tx.vout.append(CTxOut(int(value-self.relayfee*tx_size*COIN/1000), CScript([b'a']))) rawtx = self.nodes[0].signrawtransaction(ToHex(tx))["hex"] - try: - self.nodes[0].sendrawtransaction(rawtx) - except JSONRPCException as exp: - assert(not should_pass and using_sequence_locks) - assert_equal(exp.error["message"], NOT_FINAL_ERROR) + if (using_sequence_locks and not should_pass): + # This transaction should be rejected + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, rawtx) else: - assert(should_pass or not using_sequence_locks) - # Recalculate utxos if we successfully sent the transaction + # This raw transaction should be accepted + self.nodes[0].sendrawtransaction(rawtx) utxos = self.nodes[0].listunspent() # Test that sequence locks on unconfirmed inputs must have nSequence @@ -239,14 +232,13 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee*COIN), CScript([b'a']))] tx.rehash() - try: - node.sendrawtransaction(ToHex(tx)) - except JSONRPCException as exp: - assert_equal(exp.error["message"], NOT_FINAL_ERROR) - assert(orig_tx.hash in node.getrawmempool()) + if (orig_tx.hash in node.getrawmempool()): + # sendrawtransaction should fail if the tx is in the mempool + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, node.sendrawtransaction, ToHex(tx)) else: - # orig_tx must not be in mempool - assert(orig_tx.hash not in node.getrawmempool()) + # sendrawtransaction should succeed if the tx is not in the mempool + node.sendrawtransaction(ToHex(tx)) + return tx test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True) @@ -295,12 +287,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): tx5.vout[0].nValue += int(utxos[0]["amount"]*COIN) raw_tx5 = self.nodes[0].signrawtransaction(ToHex(tx5))["hex"] - try: - self.nodes[0].sendrawtransaction(raw_tx5) - except JSONRPCException as exp: - assert_equal(exp.error["message"], NOT_FINAL_ERROR) - else: - assert(False) + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, raw_tx5) # Test mempool-BIP68 consistency after reorg # @@ -373,12 +360,7 @@ def test_bip68_not_consensus(self): tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))] tx3.rehash() - try: - self.nodes[0].sendrawtransaction(ToHex(tx3)) - except JSONRPCException as exp: - assert_equal(exp.error["message"], NOT_FINAL_ERROR) - else: - assert(False) + assert_raises_jsonrpc(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx3)) # make a block that violates bip68; ensure that the tip updates tip = int(self.nodes[0].getbestblockhash(), 16) diff --git a/qa/rpc-tests/bipdersig.py b/qa/rpc-tests/bipdersig.py index fa54bc2749f4..371cc41bb714 100755 --- a/qa/rpc-tests/bipdersig.py +++ b/qa/rpc-tests/bipdersig.py @@ -68,12 +68,8 @@ def run_test(self): if (self.nodes[0].getblockcount() != cnt + 1051): raise AssertionError("Failed to mine a version=3 block") - # Mine 1 old-version blocks - try: - self.nodes[1].generate(1) - raise AssertionError("Succeeded to mine a version=2 block after 950 version=3 blocks") - except JSONRPCException: - pass + # Mine 1 old-version blocks. This should fail + assert_raises_jsonrpc(-1, "CreateNewBlock: TestBlockValidity failed: bad-version(0x00000002)", self.nodes[1].generate, 1) self.sync_all() if (self.nodes[0].getblockcount() != cnt + 1051): raise AssertionError("Accepted a version=2 block after 950 version=3 blocks") diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py index 4896468e03bb..3472841c1795 100755 --- a/qa/rpc-tests/blockchain.py +++ b/qa/rpc-tests/blockchain.py @@ -14,10 +14,9 @@ from decimal import Decimal from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException from test_framework.util import ( assert_equal, - assert_raises, + assert_raises_jsonrpc, assert_is_hex_string, assert_is_hash_string, start_nodes, @@ -82,8 +81,7 @@ def _test_gettxoutsetinfo(self): def _test_getblockheader(self): node = self.nodes[0] - assert_raises( - JSONRPCException, lambda: node.getblockheader('nonsense')) + assert_raises_jsonrpc(-5, "Block not found", node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py index 633e70125a93..58bf373f0c1b 100755 --- a/qa/rpc-tests/disablewallet.py +++ b/qa/rpc-tests/disablewallet.py @@ -31,19 +31,10 @@ def run_test (self): x = self.nodes[0].validateaddress('ycwedq2f3sz2Yf9JqZsBCQPxp18WU3Hp4J') assert(x['isvalid'] == True) - # Checking mining to an address without a wallet - try: - self.nodes[0].generatetoaddress(1, 'ycwedq2f3sz2Yf9JqZsBCQPxp18WU3Hp4J') - except JSONRPCException as e: - assert("Invalid address" not in e.error['message']) - assert("ProcessNewBlock, block not accepted" not in e.error['message']) - assert("Couldn't create new block" not in e.error['message']) - - try: - self.nodes[0].generatetoaddress(1, '7TSBtVu959hGEGPKyHjJz9k55RpWrPffXz') - raise AssertionError("Must not mine to invalid address!") - except JSONRPCException as e: - assert("Invalid address" in e.error['message']) + # Checking mining to an address without a wallet. Generating to a valid address should succeed + # but generating to an invalid address will fail. + self.nodes[0].generatetoaddress(1, 'ycwedq2f3sz2Yf9JqZsBCQPxp18WU3Hp4J') + assert_raises_jsonrpc(-5, "Invalid address", self.nodes[0].generatetoaddress, 1, '7TSBtVu959hGEGPKyHjJz9k55RpWrPffXz') if __name__ == '__main__': DisableWalletTest ().main () diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py index 8442c545dda7..057b51afe1a8 100755 --- a/qa/rpc-tests/getblocktemplate_proposals.py +++ b/qa/rpc-tests/getblocktemplate_proposals.py @@ -106,7 +106,7 @@ def run_test(self): # Test 3: Truncated final tx lastbyte = txlist[-1].pop() - assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a') + assert_raises_jsonrpc(-22, "Block decode failed", assert_template, node, tmpl, txlist, 'n/a') txlist[-1].append(lastbyte) # Test 4: Add an invalid tx to the end (duplicate of gen tx) @@ -127,7 +127,7 @@ def run_test(self): # Test 7: Bad tx count txlist.append(b'') - assert_raises(JSONRPCException, assert_template, node, tmpl, txlist, 'n/a') + assert_raises_jsonrpc(-22, 'Block decode failed', assert_template, node, tmpl, txlist, 'n/a') txlist.pop() # Test 8: Bad bits diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index b4caf79e2dbf..2fdc39dbf72b 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -25,11 +25,7 @@ def run_test(self): # Keep creating keys addr = nodes[0].getnewaddress() - try: - addr = nodes[0].getnewaddress() - raise AssertionError('Keypool should be exhausted after one address') - except JSONRPCException as e: - assert(e.error['code']==-12) + assert_raises_jsonrpc(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress) # put three new keys in the keypool nodes[0].walletpassphrase('test', 12000) @@ -44,11 +40,7 @@ def run_test(self): # assert that three unique addresses were returned assert(len(addr) == 3) # the next one should fail - try: - addr = nodes[0].getrawchangeaddress() - raise AssertionError('Keypool should be exhausted after three addresses') - except JSONRPCException as e: - assert(e.error['code']==-12) + assert_raises_jsonrpc(-12, "Keypool ran out", nodes[0].getrawchangeaddress) # refill keypool with three new addresses nodes[0].walletpassphrase('test', 1) @@ -61,11 +53,7 @@ def run_test(self): nodes[0].generate(1) nodes[0].generate(1) nodes[0].generate(1) - try: - nodes[0].generate(1) - raise AssertionError('Keypool should be exhausted after three addesses') - except JSONRPCException as e: - assert(e.error['code']==-12) + assert_raises_jsonrpc(-12, "Keypool ran out", nodes[0].generate, 1) def setup_network(self): self.nodes = start_nodes(1, self.options.tmpdir, [['-usehd=0']]) diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py index d475aabdf821..feec8a7fd923 100755 --- a/qa/rpc-tests/mempool_packages.py +++ b/qa/rpc-tests/mempool_packages.py @@ -124,10 +124,7 @@ def run_test(self): assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 1000) # Adding one more transaction on to the chain should fail. - try: - self.chain_transaction(self.nodes[0], txid, vout, value, fee, 1) - except JSONRPCException as e: - self.log.info("too-long-ancestor-chain successfully rejected") + assert_raises_jsonrpc(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], txid, vout, value, fee, 1) # Check that prioritising a tx before it's added to the mempool works # First clear the mempool by mining a block. @@ -167,19 +164,19 @@ def run_test(self): for i in range(10): transaction_package.append({'txid': txid, 'vout': i, 'amount': sent_value}) - for i in range(MAX_DESCENDANTS): + # Sign and send up to MAX_DESCENDANT transactions chained off the parent tx + for i in range(MAX_DESCENDANTS - 1): utxo = transaction_package.pop(0) - try: - (txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) - for j in range(10): - transaction_package.append({'txid': txid, 'vout': j, 'amount': sent_value}) - if i == MAX_DESCENDANTS - 2: - mempool = self.nodes[0].getrawmempool(True) - assert_equal(mempool[parent_transaction]['descendantcount'], MAX_DESCENDANTS) - except JSONRPCException as e: - self.log.info(e.error['message']) - assert_equal(i, MAX_DESCENDANTS - 1) - self.log.info("tx that would create too large descendant package successfully rejected") + (txid, sent_value) = self.chain_transaction(self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) + for j in range(10): + transaction_package.append({'txid': txid, 'vout': j, 'amount': sent_value}) + + mempool = self.nodes[0].getrawmempool(True) + assert_equal(mempool[parent_transaction]['descendantcount'], MAX_DESCENDANTS) + + # Sending one more chained transaction will fail + utxo = transaction_package.pop(0) + assert_raises_jsonrpc(-26, "too-long-mempool-chain", self.chain_transaction, self.nodes[0], utxo['txid'], utxo['vout'], utxo['amount'], fee, 10) # TODO: check that node1's mempool is as expected diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py index 9b64610d61d5..07992e838222 100755 --- a/qa/rpc-tests/mempool_reorg.py +++ b/qa/rpc-tests/mempool_reorg.py @@ -30,9 +30,10 @@ def setup_network(self): self.sync_all() def run_test(self): - start_count = self.nodes[0].getblockcount() + # Start with a 200 block chain + assert_equal(self.nodes[0].getblockcount(), 200) - # Mine three blocks. After this, nodes[0] blocks + # Mine four blocks. After this, nodes[0] blocks # 101, 102, and 103 are spend-able. new_blocks = self.nodes[1].generate(4) self.sync_all() @@ -52,19 +53,21 @@ def run_test(self): spend_102_raw = create_tx(self.nodes[0], coinbase_txids[2], node0_address, 499.9) spend_103_raw = create_tx(self.nodes[0], coinbase_txids[3], node0_address, 499.9) - # Create a block-height-locked transaction which will be invalid after reorg + # Create a transaction which is time-locked to two blocks in the future timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 499.9}) # Set the time lock timelock_tx = timelock_tx.replace("ffffffff", "11111191", 1) timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000" timelock_tx = self.nodes[0].signrawtransaction(timelock_tx)["hex"] - assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx) + # This will raise an exception because the timelock transaction is too immature to spend + assert_raises_jsonrpc(-26, "non-final", self.nodes[0].sendrawtransaction, timelock_tx) # Broadcast and mine spend_102 and 103: spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw) spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw) self.nodes[0].generate(1) - assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx) + # Time-locked transaction is still too immature to spend + assert_raises_jsonrpc(-26,'non-final', self.nodes[0].sendrawtransaction, timelock_tx) # Create 102_1 and 103_1: spend_102_1_raw = create_tx(self.nodes[0], spend_102_id, node1_address, 499.8) @@ -73,6 +76,7 @@ def run_test(self): # Broadcast and mine 103_1: spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw) last_block = self.nodes[0].generate(1) + # Time-locked transaction can now be spent timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx) # ... now put spend_101 and spend_102_1 in memory pools: @@ -85,6 +89,8 @@ def run_test(self): for node in self.nodes: node.invalidateblock(last_block[0]) + # Time-locked transaction is now too immature and has been removed from the mempool + # spend_103_1 has been re-orged out of the chain and is back in the mempool assert_equal(set(self.nodes[0].getrawmempool()), {spend_101_id, spend_102_1_id, spend_103_1_id}) # Use invalidateblock to re-org back and make all those coinbase spends diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py index 88c4a44cc222..08ca626e71a8 100755 --- a/qa/rpc-tests/mempool_spendcoinbase.py +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -45,7 +45,7 @@ def run_test(self): spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0]) # coinbase at height 102 should be too immature to spend - assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, spends_raw[1]) + assert_raises_jsonrpc(-26,"bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, spends_raw[1], False, False, True) # mempool should have just spend_101: assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ]) diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py index 22d1f63e01b7..5dd3e65b8309 100755 --- a/qa/rpc-tests/nulldummy.py +++ b/qa/rpc-tests/nulldummy.py @@ -63,29 +63,29 @@ def run_test(self): self.log.info("Test 1: NULLDUMMY compliant base transactions should be accepted to mempool and mined before activation [430]") test1txs = [self.create_transaction(self.nodes[0], coinbase_txid[0], self.ms_address, 49)] - txid1 = self.tx_submit(self.nodes[0], test1txs[0]) + txid1 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[0].serialize()), True) test1txs.append(self.create_transaction(self.nodes[0], txid1, self.ms_address, 48)) - txid2 = self.tx_submit(self.nodes[0], test1txs[1]) + txid2 = self.nodes[0].sendrawtransaction(bytes_to_hex_str(test1txs[1].serialize()), True) self.block_submit(self.nodes[0], test1txs, True) self.log.info("Test 2: Non-NULLDUMMY base multisig transaction should not be accepted to mempool before activation") test2tx = self.create_transaction(self.nodes[0], txid2, self.ms_address, 47) trueDummy(test2tx) - txid4 = self.tx_submit(self.nodes[0], test2tx, NULLDUMMY_ERROR) + assert_raises_jsonrpc(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test2tx.serialize()), True) self.log.info("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]") self.block_submit(self.nodes[0], [test2tx], True) - self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") - test4tx = self.create_transaction(self.nodes[0], txid4, self.address, 46) + self.log.info ("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") + test4tx = self.create_transaction(self.nodes[0], test2tx.hash, self.address, 46) test6txs=[CTransaction(test4tx)] trueDummy(test4tx) - self.tx_submit(self.nodes[0], test4tx, NULLDUMMY_ERROR) + assert_raises_jsonrpc(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test4tx.serialize()), True) self.block_submit(self.nodes[0], [test4tx]) self.log.info("Test 6: NULLDUMMY compliant transactions should be accepted to mempool and in block after activation [432]") for i in test6txs: - self.tx_submit(self.nodes[0], i) + self.nodes[0].sendrawtransaction(bytes_to_hex_str(i.serialize()), True) self.block_submit(self.nodes[0], test6txs, True) @@ -100,19 +100,8 @@ def create_transaction(self, node, txid, to_address, amount): return tx - def tx_submit(self, node, tx, msg = ""): - tx.rehash() - try: - node.sendrawtransaction(bytes_to_hex_str(tx.serialize()), True) - except JSONRPCException as exp: - assert_equal(exp.error["message"], msg) - else: - assert_equal('', msg) - return tx.hash - - - def block_submit(self, node, txs, accept = False): - dip4_activated = self.lastblockheight + 1 >= 432 + def block_submit(self, node, txs, witness = False, accept = False): + dip4_activated = self.lastblockheight + 1 >= 432 block = create_block(self.tip, create_coinbase(self.lastblockheight + 1, dip4_activated=dip4_activated), self.lastblocktime + 1) block.nVersion = 4 for tx in txs: diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py index c503f3e12107..f8fb1e7a269e 100755 --- a/qa/rpc-tests/prioritise_transaction.py +++ b/qa/rpc-tests/prioritise_transaction.py @@ -109,13 +109,9 @@ def run_test(self): tx_hex = self.nodes[0].signrawtransaction(raw_tx)["hex"] tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"] - try: - self.nodes[0].sendrawtransaction(tx_hex) - except JSONRPCException as exp: - assert_equal(exp.error['code'], -26) # insufficient fee - assert(tx_id not in self.nodes[0].getrawmempool()) - else: - assert(False) + # This will raise an exception due to min relay fee not being met + assert_raises_jsonrpc(-26, "66: min relay fee not met", self.nodes[0].sendrawtransaction, tx2_hex) + assert(tx2_id not in self.nodes[0].getrawmempool()) # This is a less than 1000-byte transaction, so just set the fee # to be the minimum for a 1000 byte transaction and check that it is diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py index 220bf4ddd072..8720a345cea5 100755 --- a/qa/rpc-tests/rpcbind_test.py +++ b/qa/rpc-tests/rpcbind_test.py @@ -92,11 +92,7 @@ def run_test(self): # Check that with invalid rpcallowip, we are denied self.run_allowip_test([non_loopback_ip], non_loopback_ip, defaultport) - try: - self.run_allowip_test(['1.1.1.1'], non_loopback_ip, defaultport) - assert(not 'Connection not denied by rpcallowip as expected') - except JSONRPCException: - pass + assert_raises_jsonrpc(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, ['1.1.1.1'], non_loopback_ip, defaultport) if __name__ == '__main__': RPCBindTest().main() diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py index c43447b99950..70c1b61ba67a 100755 --- a/qa/rpc-tests/wallet.py +++ b/qa/rpc-tests/wallet.py @@ -72,7 +72,7 @@ def run_test (self): unspent_0 = self.nodes[2].listunspent()[0] unspent_0 = {"txid": unspent_0["txid"], "vout": unspent_0["vout"]} self.nodes[2].lockunspent(False, [unspent_0]) - assert_raises_message(JSONRPCException, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 200) + assert_raises_jsonrpc(-4, "Insufficient funds", self.nodes[2].sendtoaddress, self.nodes[2].getnewaddress(), 200) assert_equal([unspent_0], self.nodes[2].listlockunspent()) self.nodes[2].lockunspent(True, [unspent_0]) assert_equal(len(self.nodes[2].listlockunspent()), 0) @@ -255,19 +255,11 @@ def run_test (self): txObj = self.nodes[0].gettransaction(txId) assert_equal(txObj['amount'], Decimal('-0.0001')) - try: - txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1f-4") - except JSONRPCException as e: - assert("Invalid amount" in e.error['message']) - else: - raise AssertionError("Must not parse invalid amounts") + # This will raise an exception because the amount type is wrong + assert_raises_jsonrpc(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4") - - try: - self.nodes[0].generate("2") - raise AssertionError("Must not accept strings as numeric") - except JSONRPCException as e: - assert("not an integer" in e.error['message']) + # This will raise an exception since generate does not accept a string + assert_raises_jsonrpc(-1, "not an integer", self.nodes[0].generate, "2") # Import address and private key to check correct behavior of spendable unspents # 1. Send some coins to generate new UTXO @@ -398,7 +390,7 @@ def run_test (self): node0_balance = self.nodes[0].getbalance() # With walletrejectlongchains we will not create the tx and store it in our wallet. - assert_raises_message(JSONRPCException, "mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01')) + assert_raises_jsonrpc(-4, "Transaction has too long of a mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01')) # Verify nothing new in wallet assert_equal(total_txs, len(self.nodes[0].listtransactions("*",99999))) From 594b78fdf5dcb31b7c93b89839de066648c68cb7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 16 Mar 2017 12:02:54 +0100 Subject: [PATCH 003/987] Merge #9921: build: Probe MSG_DONTWAIT in the same way as MSG_NOSIGNAL a4d1c9f compat: use `unsigned int` instead of `u_int` (Wladimir J. van der Laan) 25da1ee build: cleanup: define MSG_DONTWAIT/MSG_NO_SIGNAL locally (Wladimir J. van der Laan) c459d50 build: Probe MSG_DONTWAIT in the same way as MSG_NOSIGNAL (Wladimir J. van der Laan) Tree-SHA512: 60d79d69439bb181465e4244aa5ddc28bbd84f69c0ca0c753956b3798c9022394e29d791bc085fe7ffb1268c64c789a57e24797daad63525bb776088188ff9ae fix merge error in configure.ac Signed-off-by: Pasta --- configure.ac | 8 ++++++++ src/compat.h | 11 ++--------- src/net.cpp | 7 ++++++- src/netbase.cpp | 2 +- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/configure.ac b/configure.ac index e07ba70292f8..830c3ba88213 100644 --- a/configure.ac +++ b/configure.ac @@ -603,6 +603,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [ AC_MSG_RESULT(no)] ) +dnl Check for MSG_DONTWAIT +AC_MSG_CHECKING(for MSG_DONTWAIT) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[ int f = MSG_DONTWAIT; ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_DONTWAIT, 1,[Define this symbol if you have MSG_DONTWAIT]) ], + [ AC_MSG_RESULT(no)] +) + dnl Check for mallopt(M_ARENA_MAX) (to set glibc arenas) AC_MSG_CHECKING(for mallopt M_ARENA_MAX) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], diff --git a/src/compat.h b/src/compat.h index 2e9663b8d63f..7c7b0b3d7301 100644 --- a/src/compat.h +++ b/src/compat.h @@ -47,10 +47,8 @@ #include #endif -#ifdef WIN32 -#define MSG_DONTWAIT 0 -#else -typedef u_int SOCKET; +#ifndef WIN32 +typedef unsigned int SOCKET; #include "errno.h" #define WSAGetLastError() errno #define WSAEINVAL EINVAL @@ -74,11 +72,6 @@ typedef u_int SOCKET; #define MAX_PATH 1024 #endif -// As Solaris does not have the MSG_NOSIGNAL flag for send(2) syscall, it is defined as 0 -#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL) -#define MSG_NOSIGNAL 0 -#endif - #if HAVE_DECL_STRNLEN == 0 size_t strnlen( const char *start, size_t max_len); #endif // HAVE_DECL_STRNLEN diff --git a/src/net.cpp b/src/net.cpp index 79ca7982972c..00cab7b419b5 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -52,10 +52,15 @@ // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization. #define FEELER_SLEEP_WINDOW 1 -#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL) +#if !defined(HAVE_MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif +// MSG_DONTWAIT is not available on some platforms, if it doesn't exist define it as 0 +#if !defined(HAVE_MSG_DONTWAIT) +#define MSG_DONTWAIT 0 +#endif + // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h. // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version. #ifdef WIN32 diff --git a/src/netbase.cpp b/src/netbase.cpp index 03e336c3deff..90a087f7e8d7 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -25,7 +25,7 @@ #include // for to_lower() #include // for startswith() and endswith() -#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL) +#if !defined(HAVE_MSG_NOSIGNAL) #define MSG_NOSIGNAL 0 #endif From ae9ca8459d83a66aa1b81ae541a8bfb83afc9fa0 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 17 Mar 2017 10:28:50 +0100 Subject: [PATCH 004/987] Merge #10010: util: rename variable to avoid shadowing 9350e13 util: rename variable to avoid shadowing (Pavol Rusnak) Tree-SHA512: 8abc09fdb134c913e823754f3f02a4d8ef120a73f252fbc1217dbd2bdd4ed4fffce92d823a66d1fe51607dc021065df8826f21274ef26e55d82575e96d07224f --- src/util.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util.h b/src/util.h index eda300bdeec9..aa303761d9de 100644 --- a/src/util.h +++ b/src/util.h @@ -40,7 +40,7 @@ #ifdef ENABLE_DASH_DEBUG #define DBG( x ) x #else -#define DBG( x ) +#define DBG( x ) #endif //Dash only features @@ -103,8 +103,8 @@ std::string SafeStringFormat(const std::string& fmt, const Args&... args) { try { return tinyformat::format(fmt, args...); - } catch (std::runtime_error& e) { - std::string message = tinyformat::format("\n****TINYFORMAT ERROR****\n err=\"%s\"\n fmt=\"%s\"\n", e.what(), fmt); + } catch (std::runtime_error& fmterr) { + std::string message = tinyformat::format("\n****TINYFORMAT ERROR****\n err=\"%s\"\n fmt=\"%s\"\n", fmterr.what(), fmt); fprintf(stderr, "%s", message.c_str()); return message; } From aee4472acef828fabbc95af02388c6d0bb832707 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 17 Mar 2017 14:30:48 +0100 Subject: [PATCH 005/987] Merge #9974: Add basic Qt wallet test 9576b01 Enable xvfb in travis to allow running test_bitcoin-qt (Russell Yanofsky) 9e6817e Add new test_bitcoin-qt static library dependencies (Russell Yanofsky) 2754ef1 Add simple qt wallet test sending a transaction (Russell Yanofsky) b61b34c Add braces to if statements in Qt test_main (Russell Yanofsky) cc9503c Make qt test compatible with TestChain100Setup framework (Russell Yanofsky) 91e3035 Make test_bitcoin.cpp compatible with Qt Test framework (Russell Yanofsky) Tree-SHA512: da491181848b8c39138e997ae5ff2df0b16eef2d9cdd0a965229b1a28d4fa862d5f1ef314a1736e5050e88858f329124d15c689659fc6e50fefde769ba24e523 remove line, testing bitcoin -> dash, testing bitcoin -> dash, testing resolve name conflict, testing bitcoin -> dash re-add test fixture line code review, fix tests Signed-off-by: Pasta move ExceptionInitializer into test_dash_main.cpp remove witness from nulldummy.py Signed-off-by: Pasta change error text to match expected Signed-off-by: Pasta --- ci/matrix.sh | 2 +- ci/test_unittests.sh | 6 ++ qa/rpc-tests/nulldummy.py | 2 +- qa/rpc-tests/prioritise_transaction.py | 2 +- src/Makefile.qttest.include | 24 ++++-- src/Makefile.test.include | 1 + src/qt/test/rpcnestedtests.cpp | 4 + src/qt/test/test_main.cpp | 45 +++++++---- src/qt/test/wallettests.cpp | 104 +++++++++++++++++++++++++ src/qt/test/wallettests.h | 15 ++++ src/test/test_dash.cpp | 60 ++------------ src/test/test_dash_main.cpp | 58 ++++++++++++++ 12 files changed, 247 insertions(+), 76 deletions(-) create mode 100644 src/qt/test/wallettests.cpp create mode 100644 src/qt/test/wallettests.h create mode 100644 src/test/test_dash_main.cpp diff --git a/ci/matrix.sh b/ci/matrix.sh index 5afcbee0b549..91ce9658c026 100755 --- a/ci/matrix.sh +++ b/ci/matrix.sh @@ -66,7 +66,7 @@ elif [ "$BUILD_TARGET" = "linux64" ]; then export RUN_TESTS=true elif [ "$BUILD_TARGET" = "linux64_nowallet" ]; then export HOST=x86_64-unknown-linux-gnu - export PACKAGES="python3" + export PACKAGES="python3 xvfb" export DEP_OPTS="NO_WALLET=1" export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" elif [ "$BUILD_TARGET" = "linux64_release" ]; then diff --git a/ci/test_unittests.sh b/ci/test_unittests.sh index f5af7e39637e..9b0516a5517b 100755 --- a/ci/test_unittests.sh +++ b/ci/test_unittests.sh @@ -19,6 +19,12 @@ export WINEDEBUG=fixme-all export BOOST_TEST_LOG_LEVEL=test_suite cd build-ci/dashcore-$BUILD_TARGET + +if [ "$RUN_TESTS" = "true" -a "${DEP_OPTS#*NO_QT=1}" = "$DEP_OPTS" ]; then + export DISPLAY=:99.0; + /sbin/start-stop-daemon --start --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac; +fi + if [ "$DIRECT_WINE_EXEC_TESTS" = "true" ]; then # Inside Docker, binfmt isn't working so we can't trust in make invoking windows binaries correctly wine ./src/test/test_dash.exe diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py index 5dd3e65b8309..492f358e1aae 100755 --- a/qa/rpc-tests/nulldummy.py +++ b/qa/rpc-tests/nulldummy.py @@ -100,7 +100,7 @@ def create_transaction(self, node, txid, to_address, amount): return tx - def block_submit(self, node, txs, witness = False, accept = False): + def block_submit(self, node, txs, accept = False): dip4_activated = self.lastblockheight + 1 >= 432 block = create_block(self.tip, create_coinbase(self.lastblockheight + 1, dip4_activated=dip4_activated), self.lastblocktime + 1) block.nVersion = 4 diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py index f8fb1e7a269e..ac74ca73a923 100755 --- a/qa/rpc-tests/prioritise_transaction.py +++ b/qa/rpc-tests/prioritise_transaction.py @@ -110,7 +110,7 @@ def run_test(self): tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"] # This will raise an exception due to min relay fee not being met - assert_raises_jsonrpc(-26, "66: min relay fee not met", self.nodes[0].sendrawtransaction, tx2_hex) + assert_raises_jsonrpc(-26, "66: insufficient priority", self.nodes[0].sendrawtransaction, tx2_hex) assert(tx2_id not in self.nodes[0].getrawmempool()) # This is a less than 1000-byte transaction, so just set the fee diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index efca183cb6e6..63324be321eb 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -10,10 +10,12 @@ TEST_QT_MOC_CPP = \ qt/test/moc_compattests.cpp \ qt/test/moc_rpcnestedtests.cpp \ qt/test/moc_trafficgraphdatatests.cpp \ - qt/test/moc_uritests.cpp + qt/test/moc_uritests.cpp if ENABLE_WALLET -TEST_QT_MOC_CPP += qt/test/moc_paymentservertests.cpp +TEST_QT_MOC_CPP += \ + qt/test/moc_paymentservertests.cpp \ + qt/test/moc_wallettests.cpp endif TEST_QT_H = \ @@ -22,7 +24,16 @@ TEST_QT_H = \ qt/test/uritests.h \ qt/test/paymentrequestdata.h \ qt/test/paymentservertests.h \ - qt/test/trafficgraphdatatests.h + qt/test/trafficgraphdatatests.h \ + qt/test/wallettests.h + +TEST_BITCOIN_CPP = \ + test/test_dash.cpp \ + test/testutil.cpp + +TEST_BITCOIN_H = \ + test/test_dash.h \ + test/testutil.h qt_test_test_dash_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_TEST_INCLUDES) $(PROTOBUF_CFLAGS) @@ -33,10 +44,13 @@ qt_test_test_dash_qt_SOURCES = \ qt/test/test_main.cpp \ qt/test/uritests.cpp \ qt/test/trafficgraphdatatests.cpp \ - $(TEST_QT_H) + $(TEST_QT_H) \ + $(TEST_BITCOIN_CPP) \ + $(TEST_BITCOIN_H) if ENABLE_WALLET qt_test_test_dash_qt_SOURCES += \ - qt/test/paymentservertests.cpp + qt/test/paymentservertests.cpp \ + qt/test/wallettests.cpp endif nodist_qt_test_test_dash_qt_SOURCES = $(TEST_QT_MOC_CPP) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index b7285e91a899..cd56343a29c3 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -129,6 +129,7 @@ BITCOIN_TESTS =\ test/subsidy_tests.cpp \ test/test_dash.cpp \ test/test_dash.h \ + test/test_dash_main.cpp \ test/test_random.h \ test/testutil.cpp \ test/testutil.h \ diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index d85da3d46cd6..30b9c9233072 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -155,11 +155,15 @@ void RPCNestedTests::rpcNestedTests() QVERIFY_EXCEPTION_THROWN(RPCConsole::RPCExecuteCommandLine(result, "rpcNestedTest(abc,,)"), std::runtime_error); //don't tollerate empty arguments when using , #endif + UnloadBlockIndex(); delete pcoinsTip; + pcoinsTip = nullptr; llmq::DestroyLLMQSystem(); delete deterministicMNManager; delete pcoinsdbview; + pcoinsdbview = nullptr; delete pblocktree; + pblocktree = nullptr; delete evoDb; boost::filesystem::remove_all(boost::filesystem::path(path)); diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index 3bc073b13d7c..c73459b3aa58 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -8,7 +8,6 @@ #endif #include "chainparams.h" -#include "key.h" #include "rpcnestedtests.h" #include "util.h" #include "uritests.h" @@ -17,20 +16,31 @@ #ifdef ENABLE_WALLET #include "paymentservertests.h" +#include "wallettests.h" #endif -#include +#include #include #include #include -#if defined(QT_STATICPLUGIN) && QT_VERSION < 0x050000 +#if defined(QT_STATICPLUGIN) #include +#if QT_VERSION < 0x050000 Q_IMPORT_PLUGIN(qcncodecs) Q_IMPORT_PLUGIN(qjpcodecs) Q_IMPORT_PLUGIN(qtwcodecs) Q_IMPORT_PLUGIN(qkrcodecs) +#else +#if defined(QT_QPA_PLATFORM_XCB) +Q_IMPORT_PLUGIN(QXcbIntegrationPlugin); +#elif defined(QT_QPA_PLATFORM_WINDOWS) +Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); +#elif defined(QT_QPA_PLATFORM_COCOA) +Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin); +#endif +#endif #endif extern void noui_connect(); @@ -38,7 +48,6 @@ extern void noui_connect(); // This is all you need to run all the tests int main(int argc, char *argv[]) { - ECC_Start(); SetupEnvironment(); SetupNetworking(); SelectParams(CBaseChainParams::MAIN); @@ -47,31 +56,39 @@ int main(int argc, char *argv[]) bool fInvalid = false; // Don't remove this, it's needed to access - // QCoreApplication:: in the tests - QCoreApplication app(argc, argv); + // QApplication:: and QCoreApplication:: in the tests + QApplication app(argc, argv); app.setApplicationName("Dash-Qt-test"); SSL_library_init(); URITests test1; - if (QTest::qExec(&test1) != 0) + if (QTest::qExec(&test1) != 0) { fInvalid = true; + } #ifdef ENABLE_WALLET PaymentServerTests test2; - if (QTest::qExec(&test2) != 0) + if (QTest::qExec(&test2) != 0) { fInvalid = true; + } #endif RPCNestedTests test3; - if (QTest::qExec(&test3) != 0) + if (QTest::qExec(&test3) != 0) { fInvalid = true; - + } CompatTests test4; - if (QTest::qExec(&test4) != 0) + if (QTest::qExec(&test4) != 0) { fInvalid = true; + } +#ifdef ENABLE_WALLET + WalletTests test5; + if (QTest::qExec(&test5) != 0) { + fInvalid = true; + } +#endif - TrafficGraphDataTests test5; - if (QTest::qExec(&test5) != 0) + TrafficGraphDataTests test6; + if (QTest::qExec(&test6) != 0) fInvalid = true; - ECC_Stop(); return fInvalid; } diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp new file mode 100644 index 000000000000..79c685582801 --- /dev/null +++ b/src/qt/test/wallettests.cpp @@ -0,0 +1,104 @@ +#include "wallettests.h" + +#include "qt/bitcoinamountfield.h" +#include "qt/optionsmodel.h" +#include "qt/platformstyle.h" +#include "qt/qvalidatedlineedit.h" +#include "qt/sendcoinsdialog.h" +#include "qt/sendcoinsentry.h" +#include "qt/transactiontablemodel.h" +#include "qt/walletmodel.h" +#include "test/test_dash.h" +#include "validation.h" +#include "wallet/wallet.h" + +#include +#include +#include +#include + +namespace +{ +//! Press "Yes" button in modal send confirmation dialog. +void ConfirmSend() +{ + QTimer::singleShot(0, Qt::PreciseTimer, []() { + for (QWidget* widget : QApplication::topLevelWidgets()) { + if (widget->inherits("SendConfirmationDialog")) { + SendConfirmationDialog* dialog = qobject_cast(widget); + QAbstractButton* button = dialog->button(QMessageBox::Yes); + button->setEnabled(true); + button->click(); + } + } + }); +} + +//! Send coins to address and return txid. +uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CBitcoinAddress& address, CAmount amount) +{ + QVBoxLayout* entries = sendCoinsDialog.findChild("entries"); + SendCoinsEntry* entry = qobject_cast(entries->itemAt(0)->widget()); + entry->findChild("payTo")->setText(QString::fromStdString(address.ToString())); + entry->findChild("payAmount")->setValue(amount); + uint256 txid; + boost::signals2::scoped_connection c = wallet.NotifyTransactionChanged.connect([&txid](CWallet*, const uint256& hash, ChangeType status) { + if (status == CT_NEW) txid = hash; + }); + ConfirmSend(); + QMetaObject::invokeMethod(&sendCoinsDialog, "on_sendButton_clicked"); + return txid; +} + +//! Find index of txid in transaction list. +QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid) +{ + QString hash = QString::fromStdString(txid.ToString()); + int rows = model.rowCount({}); + for (int row = 0; row < rows; ++row) { + QModelIndex index = model.index(row, 0, {}); + if (model.data(index, TransactionTableModel::TxHashRole) == hash) { + return index; + } + } + return {}; +} +} + +//! Simple qt wallet tests. +void WalletTests::walletTests() +{ + // Set up wallet and chain with 101 blocks (1 mature block for spending). + TestChain100Setup test; + test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); + bitdb.MakeMock(); + CWallet wallet("wallet_test.dat"); + bool firstRun; + wallet.LoadWallet(firstRun); + { + LOCK(wallet.cs_wallet); + wallet.SetAddressBook(test.coinbaseKey.GetPubKey().GetID(), "", "receive"); + wallet.AddKeyPubKey(test.coinbaseKey, test.coinbaseKey.GetPubKey()); + } + wallet.ScanForWalletTransactions(chainActive.Genesis(), true); + wallet.SetBroadcastTransactions(true); + + // Create widgets for sending coins and listing transactions. + std::unique_ptr platformStyle(PlatformStyle::instantiate("other")); + SendCoinsDialog sendCoinsDialog(platformStyle.get()); + OptionsModel optionsModel; + WalletModel walletModel(platformStyle.get(), &wallet, &optionsModel); + sendCoinsDialog.setModel(&walletModel); + + // Send two transactions, and verify they are added to transaction list. + TransactionTableModel* transactionTableModel = walletModel.getTransactionTableModel(); + QCOMPARE(transactionTableModel->rowCount({}), 101); + uint256 txid1 = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(CKeyID()), 5 * COIN); + uint256 txid2 = SendCoins(wallet, sendCoinsDialog, CBitcoinAddress(CKeyID()), 10 * COIN); + QCOMPARE(transactionTableModel->rowCount({}), 103); + QVERIFY(FindTx(*transactionTableModel, txid1).isValid()); + QVERIFY(FindTx(*transactionTableModel, txid2).isValid()); + + bitdb.Flush(true); + bitdb.Reset(); +} diff --git a/src/qt/test/wallettests.h b/src/qt/test/wallettests.h new file mode 100644 index 000000000000..342f7916c30b --- /dev/null +++ b/src/qt/test/wallettests.h @@ -0,0 +1,15 @@ +#ifndef BITCOIN_QT_TEST_WALLETTESTS_H +#define BITCOIN_QT_TEST_WALLETTESTS_H + +#include +#include + +class WalletTests : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void walletTests(); +}; + +#endif // BITCOIN_QT_TEST_WALLETTESTS_H diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index e57f10dc62aa..73b96f55fcff 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -2,8 +2,6 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#define BOOST_TEST_MODULE Dash Test Suite - #include "test_dash.h" #include "chainparams.h" @@ -21,7 +19,6 @@ #include "rpc/server.h" #include "rpc/register.h" #include "script/sigcache.h" -#include "stacktraces.h" #include "test/testutil.h" @@ -33,11 +30,8 @@ #include #include -#include -#include #include -std::unique_ptr g_connman; FastRandomContext insecure_rand_ctx(true); extern bool fPrintToConsole; @@ -84,11 +78,14 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha pcoinsdbview = new CCoinsViewDB(1 << 23, true); llmq::InitLLMQSystem(*evoDb, nullptr, true); pcoinsTip = new CCoinsViewCache(pcoinsdbview); - BOOST_REQUIRE(InitBlockIndex(chainparams)); + if (!InitBlockIndex(chainparams)) { + throw std::runtime_error("InitBlockIndex failed."); + } { CValidationState state; - bool ok = ActivateBestChain(state, chainparams); - BOOST_REQUIRE(ok); + if (!ActivateBestChain(state, chainparams)) { + throw std::runtime_error("ActivateBestChain failed."); + } } nScriptCheckThreads = 3; for (int i=0; i < nScriptCheckThreads-1; i++) @@ -215,48 +212,3 @@ CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(const CTransaction &txn) { return CTxMemPoolEntry(MakeTransactionRef(txn), nFee, nTime, nHeight, spendsCoinbase, sigOpCount, lp); } - -void Shutdown(void* parg) -{ - exit(EXIT_SUCCESS); -} - -void StartShutdown() -{ - exit(EXIT_SUCCESS); -} - -bool ShutdownRequested() -{ - return false; -} - -template -void translate_exception(const T &e) -{ - std::cerr << GetPrettyExceptionStr(std::current_exception()) << std::endl; - throw; -} - -template -void register_exception_translator() -{ - boost::unit_test::unit_test_monitor.register_exception_translator(&translate_exception); -} - -struct ExceptionInitializer { - ExceptionInitializer() - { - RegisterPrettyTerminateHander(); - RegisterPrettySignalHandlers(); - - register_exception_translator(); - register_exception_translator(); - register_exception_translator(); - } - ~ExceptionInitializer() - { - } -}; - -BOOST_GLOBAL_FIXTURE( ExceptionInitializer ); diff --git a/src/test/test_dash_main.cpp b/src/test/test_dash_main.cpp new file mode 100644 index 000000000000..802aaa83a506 --- /dev/null +++ b/src/test/test_dash_main.cpp @@ -0,0 +1,58 @@ +// Copyright (c) 2011-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#define BOOST_TEST_MODULE Bitcoin Test Suite + +#include "net.h" +#include "stacktraces.h" + +#include +#include + +std::unique_ptr g_connman; + +void Shutdown(void* parg) +{ + exit(EXIT_SUCCESS); +} + +void StartShutdown() +{ + exit(EXIT_SUCCESS); +} + +bool ShutdownRequested() +{ + return false; +} + +template +void translate_exception(const T &e) +{ + std::cerr << GetPrettyExceptionStr(std::current_exception()) << std::endl; + throw; +} + +template +void register_exception_translator() +{ + boost::unit_test::unit_test_monitor.register_exception_translator(&translate_exception); +} + +struct ExceptionInitializer { + ExceptionInitializer() + { + RegisterPrettyTerminateHander(); + RegisterPrettySignalHandlers(); + + register_exception_translator(); + register_exception_translator(); + register_exception_translator(); + } + ~ExceptionInitializer() + { + } +}; + +BOOST_GLOBAL_FIXTURE(ExceptionInitializer); From 8e0968faf76bba1d479890efc383710f56295c3c Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 17 Mar 2017 14:44:29 +0100 Subject: [PATCH 006/987] Merge #9690: Change 'Clear' button string to 'Reset' 9155241 Change 'Clear' button string to 'Reset' (Daniel Aleksandersen) Tree-SHA512: 9d68aaaeef88f174b29bffced81f3b2cb6a76f7a2dd8c43df4d9bd5d29cdbcf073c1f250c6bdfad12540976b1bb27a764e5033d219a1491f27f4d89ddd06e49b --- src/qt/forms/debugwindow.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index cd60a440aae5..0710120a39a1 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -659,7 +659,7 @@ - &Clear + &Reset false From 6376da03fa0693296960aa813cfef2fdfaeacdd5 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 17 Mar 2017 20:34:55 +0100 Subject: [PATCH 007/987] Merge #9818: Save watch only key timestamps when reimporting keys 7759aa2 Save watch only key timestamps when reimporting keys (Russell Yanofsky) Tree-SHA512: 433b5a78e5626fb2f3166e6c84c22eabd5239d451dc82694da95af237e034612a24f1a8bc959b7d2f2e576ce0b679be1fa4af929ebfae758c7e832056ab67061 --- qa/rpc-tests/importmulti.py | 19 +++++++++++++++++++ src/wallet/rpcdump.cpp | 10 +++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/qa/rpc-tests/importmulti.py b/qa/rpc-tests/importmulti.py index 298b6e9b86ae..ca5d42eced8d 100755 --- a/qa/rpc-tests/importmulti.py +++ b/qa/rpc-tests/importmulti.py @@ -314,6 +314,7 @@ def run_test (self): self.nodes[1].generate(100) transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00) self.nodes[1].generate(1) + timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime'] transaction = self.nodes[1].gettransaction(transactionid) self.log.info("Should import a p2sh with respective redeem script and private keys") @@ -409,6 +410,24 @@ def run_test (self): assert_equal(address_assert['ismine'], False) assert_equal('timestamp' in address_assert, False) + + # Importing existing watch only address with new timestamp should replace saved timestamp. + assert_greater_than(timestamp, watchonly_timestamp) + print("Should replace previously saved watch only timestamp.") + result = self.nodes[1].importmulti([{ + "scriptPubKey": { + "address": watchonly_address, + }, + "timestamp": "now", + }]) + assert_equal(result[0]['success'], True) + address_assert = self.nodes[1].validateaddress(watchonly_address) + assert_equal(address_assert['iswatchonly'], True) + assert_equal(address_assert['ismine'], False) + assert_equal(address_assert['timestamp'], timestamp) + watchonly_timestamp = timestamp + + # restart nodes to check for proper serialization/deserialization of watch only address stop_nodes(self.nodes) self.nodes = start_nodes(2, self.options.tmpdir) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 10e6127b4382..a054c09f465b 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -958,7 +958,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 pwallet->MarkDirty(); - if (!pwallet->HaveWatchOnly(redeemScript) && !pwallet->AddWatchOnly(redeemScript, timestamp)) { + if (!pwallet->AddWatchOnly(redeemScript, timestamp)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } @@ -975,7 +975,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 pwallet->MarkDirty(); - if (!pwallet->HaveWatchOnly(redeemDestination) && !pwallet->AddWatchOnly(redeemDestination, timestamp)) { + if (!pwallet->AddWatchOnly(redeemDestination, timestamp)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } @@ -1068,7 +1068,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 pwallet->MarkDirty(); - if (!pwallet->HaveWatchOnly(pubKeyScript) && !pwallet->AddWatchOnly(pubKeyScript, timestamp)) { + if (!pwallet->AddWatchOnly(pubKeyScript, timestamp)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } @@ -1086,7 +1086,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 pwallet->MarkDirty(); - if (!pwallet->HaveWatchOnly(scriptRawPubKey) && !pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) { + if (!pwallet->AddWatchOnly(scriptRawPubKey, timestamp)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } @@ -1160,7 +1160,7 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6 pwallet->MarkDirty(); - if (!pwallet->HaveWatchOnly(script) && !pwallet->AddWatchOnly(script, timestamp)) { + if (!pwallet->AddWatchOnly(script, timestamp)) { throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); } From eea802738052cc754f1fc88dc1758107be5a4702 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 18 Mar 2017 10:10:00 +0100 Subject: [PATCH 008/987] Merge #9987: Remove unused code 8dc957a Remove unused code (practicalswift) Tree-SHA512: c7bb286e3b92e42fec8aa1ac2491fd38be36602efca16b4bdc4e9d5ada75c11d99e7713092ec13794abd69d5ef2c732b86209a6d01710e5ebf6fc51b8a65c92a resolve usage of `MiningRequiresPeers()` remove `fMiningRequiresPeers` --- src/chainparams.cpp | 4 ---- src/chainparams.h | 3 --- src/coins.h | 1 - src/dash-tx.cpp | 16 ---------------- src/httpserver.cpp | 7 ------- src/net.cpp | 5 ----- src/net.h | 1 - src/rpc/mining.cpp | 10 ++++------ src/rpc/server.h | 1 - src/sync.cpp | 2 -- src/sync.h | 1 - src/test/key_tests.cpp | 28 ---------------------------- src/test/script_tests.cpp | 5 ----- 13 files changed, 4 insertions(+), 80 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 7336c92d9568..8c0b43b94514 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -313,7 +313,6 @@ class CMainParams : public CChainParams { consensus.llmqChainLocks = Consensus::LLMQ_400_60; consensus.llmqForInstantSend = Consensus::LLMQ_50_60; - fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = true; fRequireRoutableExternalIP = true; @@ -492,7 +491,6 @@ class CTestNetParams : public CChainParams { consensus.llmqChainLocks = Consensus::LLMQ_50_60; consensus.llmqForInstantSend = Consensus::LLMQ_50_60; - fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = false; fRequireRoutableExternalIP = true; @@ -650,7 +648,6 @@ class CDevNetParams : public CChainParams { consensus.llmqChainLocks = Consensus::LLMQ_50_60; consensus.llmqForInstantSend = Consensus::LLMQ_50_60; - fMiningRequiresPeers = true; fDefaultConsistencyChecks = false; fRequireStandard = false; fMineBlocksOnDemand = false; @@ -774,7 +771,6 @@ class CRegTestParams : public CChainParams { vFixedSeeds.clear(); //!< Regtest mode doesn't have any fixed seeds. vSeeds.clear(); //!< Regtest mode doesn't have any DNS seeds. - fMiningRequiresPeers = false; fDefaultConsistencyChecks = true; fRequireStandard = false; fRequireRoutableExternalIP = false; diff --git a/src/chainparams.h b/src/chainparams.h index f59ba102cd48..edcaeabfe574 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -63,8 +63,6 @@ class CChainParams const CBlock& GenesisBlock() const { return genesis; } const CBlock& DevNetGenesisBlock() const { return devnetGenesis; } - /** Make miner wait to have peers to avoid wasting work */ - bool MiningRequiresPeers() const { return fMiningRequiresPeers; } /** Default value for -checkmempool and -checkblockindex argument */ bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } /** Policy: Filter transactions that do not match well-defined patterns */ @@ -108,7 +106,6 @@ class CChainParams CBlock genesis; CBlock devnetGenesis; std::vector vFixedSeeds; - bool fMiningRequiresPeers; bool fDefaultConsistencyChecks; bool fRequireStandard; bool fRequireRoutableExternalIP; diff --git a/src/coins.h b/src/coins.h index e2606c7c21be..faa7632b347a 100644 --- a/src/coins.h +++ b/src/coins.h @@ -128,7 +128,6 @@ class CCoinsViewCursor virtual bool GetKey(COutPoint &key) const = 0; virtual bool GetValue(Coin &coin) const = 0; - /* Don't care about GetKeySize here */ virtual unsigned int GetValueSize() const = 0; virtual bool Valid() const = 0; diff --git a/src/dash-tx.cpp b/src/dash-tx.cpp index 5c3348e706c8..3af107e818db 100644 --- a/src/dash-tx.cpp +++ b/src/dash-tx.cpp @@ -471,22 +471,6 @@ static bool findSighashFlags(int& flags, const std::string& flagStr) return false; } -uint256 ParseHashUO(std::map& o, std::string strKey) -{ - if (!o.count(strKey)) - return uint256(); - return ParseHashUV(o[strKey], strKey); -} - -std::vector ParseHexUO(std::map& o, std::string strKey) -{ - if (!o.count(strKey)) { - std::vector emptyVec; - return emptyVec; - } - return ParseHexUV(o[strKey], strKey); -} - static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) { int nHashType = SIGHASH_ALL; diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 17fc4d9771bd..216fc811795c 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -147,13 +147,6 @@ class WorkQueue cond.wait(lock); } } - - /** Return current depth of queue */ - size_t Depth() - { - std::unique_lock lock(cs); - return queue.size(); - } }; struct HTTPPathHandler diff --git a/src/net.cpp b/src/net.cpp index 00cab7b419b5..e65a35fabca0 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2686,11 +2686,6 @@ void CConnman::MarkAddressGood(const CAddress& addr) addrman.Good(addr); } -void CConnman::AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty) -{ - addrman.Add(addr, addrFrom, nTimePenalty); -} - void CConnman::AddNewAddresses(const std::vector& vAddr, const CAddress& addrFrom, int64_t nTimePenalty) { addrman.Add(vAddr, addrFrom, nTimePenalty); diff --git a/src/net.h b/src/net.h index 4bf1a8206f59..57a8b07d7c66 100644 --- a/src/net.h +++ b/src/net.h @@ -336,7 +336,6 @@ class CConnman size_t GetAddressCount() const; void SetServices(const CService &addr, ServiceFlags nServices); void MarkAddressGood(const CAddress& addr); - void AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty = 0); void AddNewAddresses(const std::vector& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0); std::vector GetAddresses(); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 3b65ca11ad1c..1d3ea083f35a 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -488,13 +488,11 @@ UniValue getblocktemplate(const JSONRPCRequest& request) if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - if (Params().MiningRequiresPeers()) { - if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) - throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Dash Core is not connected!"); + if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0) + throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Dash Core is not connected!"); - if (IsInitialBlockDownload()) - throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is downloading blocks..."); - } + if (IsInitialBlockDownload()) + throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Dash Core is downloading blocks..."); // 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) diff --git a/src/rpc/server.h b/src/rpc/server.h index e613eaf43af6..10d4a94f4d34 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -26,7 +26,6 @@ namespace RPCServer void OnStarted(boost::function slot); void OnStopped(boost::function slot); void OnPreCommand(boost::function slot); - void OnPostCommand(boost::function slot); } class CBlockIndex; diff --git a/src/sync.cpp b/src/sync.cpp index 3995d12a8d7f..924223630ee8 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -45,8 +45,6 @@ struct CLockLocation { return mutexName + " " + sourceFile + ":" + itostr(sourceLine) + (fTry ? " (TRY)" : ""); } - std::string MutexName() const { return mutexName; } - bool fTry; private: std::string mutexName; diff --git a/src/sync.h b/src/sync.h index ce14d6410029..ea34f1c4e2b1 100644 --- a/src/sync.h +++ b/src/sync.h @@ -100,7 +100,6 @@ class CCriticalSection : public AnnotatedMixin } }; -typedef CCriticalSection CDynamicCriticalSection; /** Wrapped boost mutex: supports waiting but not recursive locking */ typedef AnnotatedMixin CWaitableCriticalSection; diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 1af3dfd60695..813411d09a0c 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -29,34 +29,6 @@ static const CBitcoinAddress addr2C("Xn7ZrYdExuk79Dm7CJCw7sfUWi2qWJSbRy"); static const std::string strAddressBad("Xta1praZQjyELweyMByXyiREw1ZRsjXzVP"); -#ifdef KEY_TESTS_DUMPINFO -void dumpKeyInfo(uint256 privkey) -{ - CKey key; - key.resize(32); - memcpy(&secret[0], &privkey, 32); - std::vector sec; - sec.resize(32); - memcpy(&sec[0], &secret[0], 32); - printf(" * secret (hex): %s\n", HexStr(sec).c_str()); - - for (int nCompressed=0; nCompressed<2; nCompressed++) - { - bool fCompressed = nCompressed == 1; - printf(" * %s:\n", fCompressed ? "compressed" : "uncompressed"); - CBitcoinSecret bsecret; - bsecret.SetSecret(secret, fCompressed); - printf(" * secret (base58): %s\n", bsecret.ToString().c_str()); - CKey key; - key.SetSecret(secret, fCompressed); - std::vector vchPubKey = key.GetPubKey(); - printf(" * pubkey (hex): %s\n", HexStr(vchPubKey).c_str()); - printf(" * address (base58): %s\n", CBitcoinAddress(vchPubKey).ToString().c_str()); - } -} -#endif - - BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(key_test1) diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index cad83e2d215a..4ec18cf0ced6 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -381,11 +381,6 @@ class TestBuilder { return comment; } - - const CScript& GetScriptPubKey() - { - return creditTx->vout[0].scriptPubKey; - } }; std::string JSONPrettyPrint(const UniValue& univalue) From dd91bd7b3a35dd9b15a857937350057021557806 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 18 Mar 2017 11:00:00 +0100 Subject: [PATCH 009/987] Merge #9911: Wshadow: various gcc fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit d7f80b6 Rename first iterator to prevent shadowing. (Pavel Janík) b42ff60 Fix shadowing of local variables. (Pavel Janík) c4b60b3 Make some global variables less-global (static) (Pavel Janík) bb2aaee Prevent -Wshadow warnings with gcc versions 4.8.5, 5.3.1 and 6.2.1. (Pavel Janík) Tree-SHA512: 3aea4e28146c8f2a31351c6e2b0cce88b6f1e567a0ea0e6131624453e7193d0904e30d81b1439d8c69e281cf0e369b895851fb882ae48d5967b5c2e2c227404e --- src/streams.h | 4 ++-- src/test/checkqueue_tests.cpp | 8 ++++---- src/test/script_tests.cpp | 28 ++++++++++++++-------------- src/torcontrol.cpp | 24 ++++++++++++------------ src/wallet/db.cpp | 8 ++++---- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/streams.h b/src/streams.h index 088a87c72d2c..57fa9a879b3f 100644 --- a/src/streams.h +++ b/src/streams.h @@ -365,8 +365,8 @@ class CDataStream return (*this); } - void GetAndClear(CSerializeData &data) { - data.insert(data.end(), begin(), end()); + void GetAndClear(CSerializeData &d) { + d.insert(d.end(), begin(), end()); clear(); } diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index fe866dc3d5fb..cac968212e3e 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -46,7 +46,7 @@ struct FakeCheckCheckCompletion { struct FailingCheck { bool fails; - FailingCheck(bool fails) : fails(fails){}; + FailingCheck(bool _fails) : fails(_fails){}; FailingCheck() : fails(true){}; bool operator()() { @@ -411,15 +411,15 @@ BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) std::unique_lock l(m); tg.create_thread([&]{ CCheckQueueControl control(queue.get()); - std::unique_lock l(m); + std::unique_lock ll(m); has_lock = true; cv.notify_one(); - cv.wait(l, [&]{return has_tried;}); + cv.wait(ll, [&]{return has_tried;}); done = true; cv.notify_one(); // Wait until the done is acknowledged // - cv.wait(l, [&]{return done_ack;}); + cv.wait(ll, [&]{return done_ack;}); }); // Wait for thread to get the lock cv.wait(l, [&](){return has_lock;}); diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 4ec18cf0ced6..13a996499be1 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -31,7 +31,7 @@ // Uncomment if you want to output updated JSON tests. // #define UPDATE_JSON_TESTS -static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; +static const unsigned int gFlags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC; unsigned int ParseScriptFlags(std::string strFlags); std::string FormatScriptFlags(unsigned int flags); @@ -801,18 +801,18 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, gFlags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); txTo12.vout[0].nValue = 2; - BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, gFlags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, gFlags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, gFlags, MutableTransactionSignatureChecker(&txTo12, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); } @@ -834,54 +834,54 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) std::vector keys; keys.push_back(key1); keys.push_back(key2); CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key3); CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key3); CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key2); // Can't re-use sig CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); keys.clear(); // Must have signatures CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23); - BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); + BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, gFlags, MutableTransactionSignatureChecker(&txTo23, 0), &err)); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err)); } diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 952149c06698..453cb1f170c1 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -662,26 +662,26 @@ void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg) } /****** Thread ********/ -struct event_base *base; -boost::thread torControlThread; +static struct event_base *gBase; +static boost::thread torControlThread; static void TorControlThread() { - TorController ctrl(base, GetArg("-torcontrol", DEFAULT_TOR_CONTROL)); + TorController ctrl(gBase, GetArg("-torcontrol", DEFAULT_TOR_CONTROL)); - event_base_dispatch(base); + event_base_dispatch(gBase); } void StartTorControl(boost::thread_group& threadGroup, CScheduler& scheduler) { - assert(!base); + assert(!gBase); #ifdef WIN32 evthread_use_windows_threads(); #else evthread_use_pthreads(); #endif - base = event_base_new(); - if (!base) { + gBase = event_base_new(); + if (!gBase) { LogPrintf("tor: Unable to create event_base\n"); return; } @@ -691,9 +691,9 @@ void StartTorControl(boost::thread_group& threadGroup, CScheduler& scheduler) void InterruptTorControl() { - if (base) { + if (gBase) { LogPrintf("tor: Thread interrupt\n"); - event_base_loopbreak(base); + event_base_loopbreak(gBase); } } @@ -701,13 +701,13 @@ void StopTorControl() { // timed_join() avoids the wallet not closing during a repair-restart. For a 'normal' wallet exit // it behaves for our cases exactly like the normal join() - if (base) { + if (gBase) { #if BOOST_VERSION >= 105000 torControlThread.try_join_for(boost::chrono::seconds(1)); #else torControlThread.timed_join(boost::posix_time::seconds(1)); #endif - event_base_free(base); - base = 0; + event_base_free(gBase); + gBase = 0; } } diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 9605c1cf81d0..4d85d445ee3c 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -604,11 +604,11 @@ bool CDB::PeriodicFlush(std::string strFile) { // Don't do this if any databases are in use int nRefCount = 0; - std::map::iterator mi = bitdb.mapFileUseCount.begin(); - while (mi != bitdb.mapFileUseCount.end()) + std::map::iterator mit = bitdb.mapFileUseCount.begin(); + while (mit != bitdb.mapFileUseCount.end()) { - nRefCount += (*mi).second; - mi++; + nRefCount += (*mit).second; + mit++; } if (nRefCount == 0) From 22563f3698f9d04b4b8f72b86b508090a195779b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 19 Mar 2017 10:13:45 +0100 Subject: [PATCH 010/987] Merge #10024: [trivial] Use log.info() instead of print() in remaining functional test cases. e722777 fix logging in nulldummy and proxy_test (John Newbery) 1f70653 Use log.info() instead of print() in importmulti.py (John Newbery) Tree-SHA512: 0e58f0a970cd93bc1e9d73c6f53ca0671b0c5135cbf92e97d8563bd8a063679bf04f8bde511c275d5f84036aed32f70d3d03679a92688952b46dc97929e0405c --- qa/rpc-tests/importmulti.py | 2 +- qa/rpc-tests/nulldummy.py | 2 +- qa/rpc-tests/proxy_test.py | 4 ++-- qa/rpc-tests/test_framework/socks5.py | 7 +++++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/qa/rpc-tests/importmulti.py b/qa/rpc-tests/importmulti.py index ca5d42eced8d..aa03c6780a20 100755 --- a/qa/rpc-tests/importmulti.py +++ b/qa/rpc-tests/importmulti.py @@ -413,7 +413,7 @@ def run_test (self): # Importing existing watch only address with new timestamp should replace saved timestamp. assert_greater_than(timestamp, watchonly_timestamp) - print("Should replace previously saved watch only timestamp.") + self.log.info("Should replace previously saved watch only timestamp.") result = self.nodes[1].importmulti([{ "scriptPubKey": { "address": watchonly_address, diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py index 492f358e1aae..736fed5fc914 100755 --- a/qa/rpc-tests/nulldummy.py +++ b/qa/rpc-tests/nulldummy.py @@ -76,7 +76,7 @@ def run_test(self): self.log.info("Test 3: Non-NULLDUMMY base transactions should be accepted in a block before activation [431]") self.block_submit(self.nodes[0], [test2tx], True) - self.log.info ("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") + self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation") test4tx = self.create_transaction(self.nodes[0], test2tx.hash, self.address, 46) test6txs=[CTransaction(test4tx)] trueDummy(test4tx) diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py index 6b2a8ed1c7cf..748e3e69f681 100755 --- a/qa/rpc-tests/proxy_test.py +++ b/qa/rpc-tests/proxy_test.py @@ -49,6 +49,7 @@ def __init__(self): self.num_nodes = 4 self.setup_clean_chain = False + def setup_nodes(self): self.have_ipv6 = test_ipv6_local() # Create two proxies on different ports # ... one unauthenticated @@ -69,7 +70,7 @@ def __init__(self): self.conf3.unauth = True self.conf3.auth = True else: - print("Warning: testing without local IPv6 support") + self.log.warning("Testing without local IPv6 support") self.serv1 = Socks5Server(self.conf1) self.serv1.start() @@ -79,7 +80,6 @@ def __init__(self): self.serv3 = Socks5Server(self.conf3) self.serv3.start() - def setup_nodes(self): # Note: proxies are not used to connect to local nodes # this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost args = [ diff --git a/qa/rpc-tests/test_framework/socks5.py b/qa/rpc-tests/test_framework/socks5.py index 450bf3775eaa..dd7624d4540e 100644 --- a/qa/rpc-tests/test_framework/socks5.py +++ b/qa/rpc-tests/test_framework/socks5.py @@ -6,6 +6,9 @@ import socket, threading, queue import traceback, sys +import logging + +logger = logging.getLogger("TestFramework.socks5") ### Protocol constants class Command: @@ -112,10 +115,10 @@ def handle(self): cmdin = Socks5Command(cmd, atyp, addr, port, username, password) self.serv.queue.put(cmdin) - print('Proxy: ', cmdin) + logger.info('Proxy: %s', cmdin) # Fall through to disconnect except Exception as e: - traceback.print_exc(file=sys.stderr) + logger.exception("socks5 request handling failed.") self.serv.queue.put(e) finally: self.conn.close() From d563222854e7070bcd25205cebb6a9a3a574a320 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 19 Mar 2017 11:26:31 +0100 Subject: [PATCH 011/987] Merge #10033: Trivial: Fix typo in key.h comment f490dae Trivial: Fix typo in key.h comment (Michael Goldstein) Tree-SHA512: 4b79bfa88313d3558edb9ab1c6d27bd45659355e81f224ba75c05ff069ebae4c9f443efd70ae274814bbb7cca8a9057942b9b867055c48e93822ac73e38a51ce --- src/key.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key.h b/src/key.h index ff5252b7a0fd..b218f2cb7222 100644 --- a/src/key.h +++ b/src/key.h @@ -45,7 +45,7 @@ class CKey //! The actual byte data std::vector > keydata; - //! Check whether the 32-byte array pointed to be vch is valid keydata. + //! Check whether the 32-byte array pointed to by vch is valid keydata. bool static Check(const unsigned char* vch); public: From de0919220b1d4289b25dc38c59894e83bdf7a644 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 20 Mar 2017 08:39:13 +0100 Subject: [PATCH 012/987] Merge #10027: Set to nullptr after delete d93b97f Set to nullptr after delete (practicalswift) Tree-SHA512: 7201cef4541557ffe31f52ce7527c4b08a2ff5aa1eae5268bdfee5b4843881f8fd115257bef6d1b4dfb71166951950a912ce87aef160ca89c2ca2ae264cfab1b set dash pointers to nullptr after deletion --- src/httpserver.cpp | 1 + src/qt/test/rpcnestedtests.cpp | 2 ++ src/test/dbwrapper_tests.cpp | 2 ++ 3 files changed, 5 insertions(+) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 216fc811795c..21b3bd090403 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -482,6 +482,7 @@ void StopHTTPServer() workQueue->WaitExit(); #endif delete workQueue; + workQueue = nullptr; } if (eventBase) { LogPrint("http", "Waiting for HTTP event thread to exit\n"); diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 30b9c9233072..cacfa5f69de6 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -160,11 +160,13 @@ void RPCNestedTests::rpcNestedTests() pcoinsTip = nullptr; llmq::DestroyLLMQSystem(); delete deterministicMNManager; + deterministicMNManager = nullptr; delete pcoinsdbview; pcoinsdbview = nullptr; delete pblocktree; pblocktree = nullptr; delete evoDb; + evoDb = nullptr; boost::filesystem::remove_all(boost::filesystem::path(path)); } diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index ca55dccf423d..371d103c7d35 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -141,6 +141,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) // Call the destructor to free leveldb LOCK delete dbw; + dbw = nullptr; // Now, set up another wrapper that wants to obfuscate the same directory CDBWrapper odbw(ph, (1 << 10), false, false, true); @@ -182,6 +183,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) // Call the destructor to free leveldb LOCK delete dbw; + dbw = nullptr; // Simulate a -reindex by wiping the existing data store CDBWrapper odbw(ph, (1 << 10), false, true, true); From 1914c2d7888b1d9bb6b325b313f64b4153cb7910 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 20 Mar 2017 15:04:59 +0100 Subject: [PATCH 013/987] Merge #10038: Add mallocinfo mode to `getmemoryinfo` RPC e141aa4 Add mallocinfo mode to `getmemoryinfo` RPC (Wladimir J. van der Laan) Tree-SHA512: e778631765c29b3b5fb94eb66e5f50a8f108a234891bdcc4883f1e6e2fdd223f7660fad987eb2d7cbda5b800482d78adc1a309a3f6f83a84c556af43ebee2ed7 --- configure.ac | 8 +++++++ src/rpc/misc.cpp | 54 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 830c3ba88213..b76ac1e816d0 100644 --- a/configure.ac +++ b/configure.ac @@ -619,6 +619,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [ AC_MSG_RESULT(no)] ) +dnl Check for malloc_info (for memory statistics information in getmemoryinfo) +AC_MSG_CHECKING(for getmemoryinfo) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[ int f = malloc_info(0, NULL); ]])], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MALLOC_INFO, 1,[Define this symbol if you have malloc_info]) ], + [ AC_MSG_RESULT(no)] +) + AC_MSG_CHECKING([for visibility attribute]) AC_LINK_IFELSE([AC_LANG_SOURCE([ int foo_def( void ) __attribute__((visibility("default"))); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 5fc2f612bf08..7810d4a6bb7d 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -25,6 +25,9 @@ #include "spork.h" #include +#ifdef HAVE_MALLOC_INFO +#include +#endif #include #include @@ -1117,16 +1120,39 @@ static UniValue RPCLockedMemoryInfo() return obj; } +#ifdef HAVE_MALLOC_INFO +static std::string RPCMallocInfo() +{ + char *ptr = nullptr; + size_t size = 0; + FILE *f = open_memstream(&ptr, &size); + if (f) { + malloc_info(0, f); + fclose(f); + if (ptr) { + std::string rv(ptr, size); + free(ptr); + return rv; + } + } + return ""; +} +#endif + UniValue getmemoryinfo(const JSONRPCRequest& request) { /* Please, avoid using the word "pool" here in the RPC interface or help, * as users will undoubtedly confuse it with the other "memory pool" */ - if (request.fHelp || request.params.size() != 0) + if (request.fHelp || request.params.size() > 1) throw std::runtime_error( - "getmemoryinfo\n" + "getmemoryinfo (\"mode\")\n" "Returns an object containing information about memory usage.\n" - "\nResult:\n" + "Arguments:\n" + "1. \"mode\" determines what kind of information is returned. This argument is optional, the default mode is \"stats\".\n" + " - \"stats\" returns general statistics about memory usage in the daemon.\n" + " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+).\n" + "\nResult (mode \"stats\"):\n" "{\n" " \"locked\": { (json object) Information about locked memory manager\n" " \"used\": xxxxx, (numeric) Number of bytes used\n" @@ -1137,13 +1163,27 @@ UniValue getmemoryinfo(const JSONRPCRequest& request) " \"chunks_free\": xxxxx, (numeric) Number unused chunks\n" " }\n" "}\n" + "\nResult (mode \"mallocinfo\"):\n" + "\"...\"\n" "\nExamples:\n" + HelpExampleCli("getmemoryinfo", "") + HelpExampleRpc("getmemoryinfo", "") ); - UniValue obj(UniValue::VOBJ); - obj.push_back(Pair("locked", RPCLockedMemoryInfo())); - return obj; + + std::string mode = (request.params.size() < 1 || request.params[0].isNull()) ? "stats" : request.params[0].get_str(); + if (mode == "stats") { + UniValue obj(UniValue::VOBJ); + obj.push_back(Pair("locked", RPCLockedMemoryInfo())); + return obj; + } else if (mode == "mallocinfo") { +#ifdef HAVE_MALLOC_INFO + return RPCMallocInfo(); +#else + throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo is only available when compiled with glibc 2.10+"); +#endif + } else { + throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode); + } } UniValue echo(const JSONRPCRequest& request) @@ -1164,7 +1204,7 @@ static const CRPCCommand commands[] = // --------------------- ------------------------ ----------------------- ---------- { "control", "debug", &debug, true, {} }, { "control", "getinfo", &getinfo, true, {} }, /* uses wallet if enabled */ - { "control", "getmemoryinfo", &getmemoryinfo, true, {} }, + { "control", "getmemoryinfo", &getmemoryinfo, true, {"mode"} }, { "util", "validateaddress", &validateaddress, true, {"address"} }, /* uses wallet if enabled */ { "util", "createmultisig", &createmultisig, true, {"nrequired","keys"} }, { "util", "verifymessage", &verifymessage, true, {"address","signature","message"} }, From 5f45198045749eb0dff9ad86ed531f1752184977 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 20 Mar 2017 17:58:40 +0100 Subject: [PATCH 014/987] Merge #9734: Add updating of chainTxData to release process 41b8821 Add updating of chainTxData to release process (Pieter Wuille) Tree-SHA512: f7d6e72b19aa83fc4851a9316d6c6a236e0e914d637525cda42c0b15a94543b8072ce67b57d6b12141332a03b64b6c715dff4d61e6e58e0197b22305b35ad65d --- doc/release-process.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release-process.md b/doc/release-process.md index 255c2c05a37f..b6ab2b2e1e09 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -21,6 +21,7 @@ Before every major release: * Update hardcoded [seeds](/contrib/seeds/README.md). TODO: Give example PR for Dash * Update [`BLOCK_CHAIN_SIZE`](/src/qt/intro.cpp) to the current size plus some overhead. +* Update `src/chainparams.cpp` chainTxData with statistics about the transaction count and rate. ### First time / New builders From 720f13d6942f6cd7e2ea82fc03d6156ab5d6f8ae Mon Sep 17 00:00:00 2001 From: pasta Date: Fri, 15 Mar 2019 14:23:30 -0500 Subject: [PATCH 015/987] add a comment linking to xvfb documentation --- ci/test_unittests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/test_unittests.sh b/ci/test_unittests.sh index 9b0516a5517b..9c88ee0fc66e 100755 --- a/ci/test_unittests.sh +++ b/ci/test_unittests.sh @@ -22,6 +22,7 @@ cd build-ci/dashcore-$BUILD_TARGET if [ "$RUN_TESTS" = "true" -a "${DEP_OPTS#*NO_QT=1}" = "$DEP_OPTS" ]; then export DISPLAY=:99.0; + # Start xvfb if needed, as documented at https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI /sbin/start-stop-daemon --start --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac; fi From 9cef545acab912aa53db3308d505b78c9fb3abea Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 3 Apr 2019 07:40:18 -0500 Subject: [PATCH 016/987] code review Signed-off-by: Pasta --- qa/rpc-tests/__init__.py | 0 qa/rpc-tests/nulldummy.py | 2 +- qa/rpc-tests/prioritise_transaction.py | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 qa/rpc-tests/__init__.py diff --git a/qa/rpc-tests/__init__.py b/qa/rpc-tests/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/qa/rpc-tests/nulldummy.py b/qa/rpc-tests/nulldummy.py index 736fed5fc914..3ad8a3235f31 100755 --- a/qa/rpc-tests/nulldummy.py +++ b/qa/rpc-tests/nulldummy.py @@ -101,7 +101,7 @@ def create_transaction(self, node, txid, to_address, amount): def block_submit(self, node, txs, accept = False): - dip4_activated = self.lastblockheight + 1 >= 432 + dip4_activated = self.lastblockheight + 1 >= 432 block = create_block(self.tip, create_coinbase(self.lastblockheight + 1, dip4_activated=dip4_activated), self.lastblocktime + 1) block.nVersion = 4 for tx in txs: diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py index ac74ca73a923..85d43a713c68 100755 --- a/qa/rpc-tests/prioritise_transaction.py +++ b/qa/rpc-tests/prioritise_transaction.py @@ -110,8 +110,8 @@ def run_test(self): tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"] # This will raise an exception due to min relay fee not being met - assert_raises_jsonrpc(-26, "66: insufficient priority", self.nodes[0].sendrawtransaction, tx2_hex) - assert(tx2_id not in self.nodes[0].getrawmempool()) + assert_raises_jsonrpc(-26, "66: min relay fee not met", self.nodes[0].sendrawtransaction, tx2_hex) + assert(tx_id not in self.nodes[0].getrawmempool()) # This is a less than 1000-byte transaction, so just set the fee # to be the minimum for a 1000 byte transaction and check that it is From 826846f154a7ea747ed4a845e14308f53c0a484f Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sat, 6 Apr 2019 12:44:43 +0300 Subject: [PATCH 017/987] Review suggestions --- qa/rpc-tests/__init__.py | 0 qa/rpc-tests/mempool_spendcoinbase.py | 2 +- qa/rpc-tests/prioritise_transaction.py | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 qa/rpc-tests/__init__.py diff --git a/qa/rpc-tests/__init__.py b/qa/rpc-tests/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py index 08ca626e71a8..1dbf8ae2581a 100755 --- a/qa/rpc-tests/mempool_spendcoinbase.py +++ b/qa/rpc-tests/mempool_spendcoinbase.py @@ -45,7 +45,7 @@ def run_test(self): spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0]) # coinbase at height 102 should be too immature to spend - assert_raises_jsonrpc(-26,"bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, spends_raw[1], False, False, True) + assert_raises_jsonrpc(-26,"bad-txns-premature-spend-of-coinbase", self.nodes[0].sendrawtransaction, spends_raw[1]) # mempool should have just spend_101: assert_equal(self.nodes[0].getrawmempool(), [ spend_101_id ]) diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py index 85d43a713c68..0da13e5ebd95 100755 --- a/qa/rpc-tests/prioritise_transaction.py +++ b/qa/rpc-tests/prioritise_transaction.py @@ -110,7 +110,7 @@ def run_test(self): tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"] # This will raise an exception due to min relay fee not being met - assert_raises_jsonrpc(-26, "66: min relay fee not met", self.nodes[0].sendrawtransaction, tx2_hex) + assert_raises_jsonrpc(-26, "66: min relay fee not met", self.nodes[0].sendrawtransaction, tx_hex) assert(tx_id not in self.nodes[0].getrawmempool()) # This is a less than 1000-byte transaction, so just set the fee From f8c3f9f7d10eb74b033a0e7fb8377803070ee381 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 10 Apr 2017 08:57:26 +0200 Subject: [PATCH 018/987] Merge #10142: Run bitcoin_test-qt under minimal QPA platform bf10264 Run bitcoin_test-qt under minimal QPA platform (Russell Yanofsky) Tree-SHA512: 35782f0d7e4dcdc27d991d5a10fcffbd2d201139293fe7917ef6f7cd7ae4d3a162ebc21f83266d821ae3bad86f62d947b047bb317f6c5899df4d6bcb4c957157 --- build-aux/m4/bitcoin_qt.m4 | 2 ++ src/qt/test/test_main.cpp | 8 ++++++++ src/qt/test/wallettests.cpp | 12 ++++++++++++ 3 files changed, 22 insertions(+) diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index e11c9b90ea6b..c3785bdcf3b7 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -130,6 +130,8 @@ AC_DEFUN([BITCOIN_QT_CONFIGURE],[ if test "x$bitcoin_cv_need_acc_widget" = "xyes"; then _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(AccessibleFactory)], [-lqtaccessiblewidgets]) fi + _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin)],[-lqminimal]) + AC_DEFINE(QT_QPA_PLATFORM_MINIMAL, 1, [Define this symbol if the minimal qt platform exists]) if test x$TARGET_OS = xwindows; then _BITCOIN_QT_CHECK_STATIC_PLUGINS([Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)],[-lqwindows]) AC_DEFINE(QT_QPA_PLATFORM_WINDOWS, 1, [Define this symbol if the qt platform is windows]) diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index c73459b3aa58..dc6a92bb3535 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -33,6 +33,9 @@ Q_IMPORT_PLUGIN(qjpcodecs) Q_IMPORT_PLUGIN(qtwcodecs) Q_IMPORT_PLUGIN(qkrcodecs) #else +#if defined(QT_QPA_PLATFORM_MINIMAL) +Q_IMPORT_PLUGIN(QMinimalIntegrationPlugin); +#endif #if defined(QT_QPA_PLATFORM_XCB) Q_IMPORT_PLUGIN(QXcbIntegrationPlugin); #elif defined(QT_QPA_PLATFORM_WINDOWS) @@ -55,6 +58,11 @@ int main(int argc, char *argv[]) bool fInvalid = false; + // Prefer the "minimal" platform for the test instead of the normal default + // platform ("xcb", "windows", or "cocoa") so tests can't unintentially + // interfere with any background GUIs and don't require extra resources. + setenv("QT_QPA_PLATFORM", "minimal", 0); + // Don't remove this, it's needed to access // QApplication:: and QCoreApplication:: in the tests QApplication app(argc, argv); diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 79c685582801..5851175860da 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -66,6 +66,18 @@ QModelIndex FindTx(const QAbstractItemModel& model, const uint256& txid) } //! Simple qt wallet tests. +// +// Test widgets can be debugged interactively calling show() on them and +// manually running the event loop, e.g.: +// +// sendCoinsDialog.show(); +// QEventLoop().exec(); +// +// This also requires overriding the default minimal Qt platform: +// +// src/qt/test/test_bitcoin-qt -platform xcb # Linux +// src/qt/test/test_bitcoin-qt -platform windows # Windows +// src/qt/test/test_bitcoin-qt -platform cocoa # macOS void WalletTests::walletTests() { // Set up wallet and chain with 101 blocks (1 mature block for spending). From fc1b3772d5dbfe8666220980c7a05a96056b0807 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 26 Jul 2017 08:11:42 +0200 Subject: [PATCH 019/987] Merge #10899: [test] Qt: Use _putenv_s instead of setenv on Windows builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0be03c7 Qt: Use _putenv_s instead of setenv on Windows builds (Brian McMichael) Pull request description: Fixes https://github.com/bitcoin/bitcoin/issues/10836 Error message I would get on `make`: ``` ... CXXLD bench/bench_bitcoin.exe OBJCXXLD qt/bitcoin-qt.exe qt/test/test_main.cpp: In function ‘int main(int, char**)’: qt/test/test_main.cpp:64:43: error: ‘setenv’ was not declared in this scope setenv("QT_QPA_PLATFORM", "minimal", 0); ^ make[2]: *** [qt/test/qt_test_test_bitcoin_qt-test_main.o] Error 1 make[2]: *** Waiting for unfinished jobs.... make[2]: Leaving directory `/home/bmcmichael/Projects/bcoin/src' make[1]: *** [all-recursive] Error 1 make[1]: Leaving directory `/home/bmcmichael/Projects/bcoin/src' make: *** [all-recursive] Error 1 ``` `setenv` function is not available from the Microsoft runtime library. Need to use `_putenv_s` instead. This solution tells the compiler to use `_putenv_s` on `WIN32` compilation (Note: this also works on 64-bit Windows instances.) and `setenv` everywhere else. I've tested builds on Windows 10 x64 and Ubuntu 16.04 with this code. Tree-SHA512: d53c996c890e3c6f22b4f2dcca718bef9168f19a6d4a29b8ff13391bfc0c8ea9c1cd16782b47c25b156dcbdff18bb19e23bfd5f6fefb1f373c9d5454a13fc969 --- src/qt/test/test_main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index dc6a92bb3535..44efc9092212 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -61,7 +61,11 @@ int main(int argc, char *argv[]) // Prefer the "minimal" platform for the test instead of the normal default // platform ("xcb", "windows", or "cocoa") so tests can't unintentially // interfere with any background GUIs and don't require extra resources. - setenv("QT_QPA_PLATFORM", "minimal", 0); + #if defined(WIN32) + _putenv_s("QT_QPA_PLATFORM", "minimal"); + #else + setenv("QT_QPA_PLATFORM", "minimal", 0); + #endif // Don't remove this, it's needed to access // QApplication:: and QCoreApplication:: in the tests From ace96a941aacc2e93af81f69909b4242582b76da Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sat, 6 Apr 2019 16:58:25 +0300 Subject: [PATCH 020/987] Drop xvfb and run tests in linux64_nowallet --- ci/matrix.sh | 3 ++- ci/test_unittests.sh | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/ci/matrix.sh b/ci/matrix.sh index 91ce9658c026..e033ee3d5ef1 100755 --- a/ci/matrix.sh +++ b/ci/matrix.sh @@ -66,9 +66,10 @@ elif [ "$BUILD_TARGET" = "linux64" ]; then export RUN_TESTS=true elif [ "$BUILD_TARGET" = "linux64_nowallet" ]; then export HOST=x86_64-unknown-linux-gnu - export PACKAGES="python3 xvfb" + export PACKAGES="python3" export DEP_OPTS="NO_WALLET=1" export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" + export RUN_TESTS=true elif [ "$BUILD_TARGET" = "linux64_release" ]; then export HOST=x86_64-unknown-linux-gnu export PACKAGES="bc python3-zmq" diff --git a/ci/test_unittests.sh b/ci/test_unittests.sh index 9c88ee0fc66e..2d221c66b683 100755 --- a/ci/test_unittests.sh +++ b/ci/test_unittests.sh @@ -20,12 +20,6 @@ export BOOST_TEST_LOG_LEVEL=test_suite cd build-ci/dashcore-$BUILD_TARGET -if [ "$RUN_TESTS" = "true" -a "${DEP_OPTS#*NO_QT=1}" = "$DEP_OPTS" ]; then - export DISPLAY=:99.0; - # Start xvfb if needed, as documented at https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI - /sbin/start-stop-daemon --start --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac; -fi - if [ "$DIRECT_WINE_EXEC_TESTS" = "true" ]; then # Inside Docker, binfmt isn't working so we can't trust in make invoking windows binaries correctly wine ./src/test/test_dash.exe From acbf0a2211d7fffaaa600ec3dc2837b16046b47d Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 17 May 2019 12:21:03 +0300 Subject: [PATCH 021/987] Bump version to 0.14.1 (#2928) --- README.md | 2 +- configure.ac | 2 +- doc/Doxyfile | 2 +- doc/README.md | 2 +- doc/README_windows.txt | 2 +- src/clientversion.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 102349e65550..d73b9895996b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Dash Core staging tree 0.14.0 +Dash Core staging tree 0.14.1 =============================== `master:` [![Build Status](https://travis-ci.org/dashpay/dash.svg?branch=master)](https://travis-ci.org/dashpay/dash) `develop:` [![Build Status](https://travis-ci.org/dashpay/dash.svg?branch=develop)](https://travis-ci.org/dashpay/dash/branches) diff --git a/configure.ac b/configure.ac index e07ba70292f8..2c7fe7957c3c 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N) AC_PREREQ([2.60]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 14) -define(_CLIENT_VERSION_REVISION, 0) +define(_CLIENT_VERSION_REVISION, 1) define(_CLIENT_VERSION_BUILD, 0) define(_CLIENT_VERSION_IS_RELEASE, false) define(_COPYRIGHT_YEAR, 2019) diff --git a/doc/Doxyfile b/doc/Doxyfile index 34b2a17a60ec..07feaf04a5c2 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -41,7 +41,7 @@ PROJECT_NAME = "Dash Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.0.0 +PROJECT_NUMBER = 0.14.1.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/README.md b/doc/README.md index cb0985cdf6a0..8f53f3771777 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,4 +1,4 @@ -Dash Core 0.14.0 +Dash Core 0.14.1 ===================== This is the official reference wallet for Dash digital currency and comprises the backbone of the Dash peer-to-peer network. You can [download Dash Core](https://www.dash.org/downloads/) or [build it yourself](#building) using the guides below. diff --git a/doc/README_windows.txt b/doc/README_windows.txt index 4432ad8925d6..d3bcc8cd22cc 100644 --- a/doc/README_windows.txt +++ b/doc/README_windows.txt @@ -1,4 +1,4 @@ -Dash Core 0.14.0 +Dash Core 0.14.1 ===================== Intro diff --git a/src/clientversion.h b/src/clientversion.h index 513373905237..aad78fb70e51 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -16,7 +16,7 @@ //! These need to be macros, as clientversion.cpp's and dash*-res.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 14 -#define CLIENT_VERSION_REVISION 0 +#define CLIENT_VERSION_REVISION 1 #define CLIENT_VERSION_BUILD 0 //! Set to true for release, false for prerelease or test build From 6edbc9cebd6efd9e089d52dda68dd14452eabc2b Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Sun, 19 May 2019 15:20:34 -0500 Subject: [PATCH 022/987] Merge bitcoin#9956: Reorganise qa directory (#2912) * Merge #9956: Reorganise qa directory 63d66ba Move src/test/bitcoin-util-test.py to test/util/bitcoin-util-test.py (John Newbery) 5b0bff4 Rename --enable-extended-rpc-tests to --enable-extended-functional-tests (John Newbery) a9bd622 Rename test/pull-tester/rpc-tests.py to test/functional/test_runner.py (John Newbery) c28ee91 Rename rpc-tests directory to functional (John Newbery) 00902c4 Rename qa directory to test (John Newbery) Tree-SHA512: ee7125c0c647d81590177beef2c8852c4ef76fdcf888096d9d4d360562a01d8d3b453345c3040487b2a043935bd1e7e80018f34462d6e02262bedbe23edcc576 resolve build errors Signed-off-by: Pasta update test_runner.py in testintegrations.sh Signed-off-by: Pasta * moved dash specific tests Signed-off-by: Pasta * dashify README.md Signed-off-by: Pasta * removed autoix*.py Signed-off-by: Pasta * change back file perms * dedashify Signed-off-by: Pasta --- .gitignore | 6 +- Makefile.am | 64 ++++++++++-- README.md | 4 +- ci/test_integrationtests.sh | 2 +- configure.ac | 24 ++--- contrib/devtools/copyright_header.py | 2 +- doc/developer-notes.md | 4 +- qa/README.md | 87 ----------------- src/Makefile.test.include | 49 +--------- src/test/README.md | 11 +-- src/test/bitcoin-util-test.py | 45 --------- src/test/buildenv.py.in | 2 - test/README.md | 97 +++++++++++++++++++ {qa/rpc-tests => test/functional}/.gitignore | 0 {qa/rpc-tests => test/functional}/README.md | 0 .../functional}/abandonconflict.py | 0 .../functional}/addressindex.py | 0 .../functional}/assumevalid.py | 0 .../functional}/autois-mempool.py | 0 .../functional}/bip65-cltv-p2p.py | 0 .../functional}/bip65-cltv.py | 0 .../functional}/bip68-112-113-p2p.py | 0 .../functional}/bip68-sequence.py | 0 .../functional}/bip9-softforks.py | 0 .../functional}/bipdersig-p2p.py | 0 .../functional}/bipdersig.py | 0 .../functional}/blockchain.py | 0 .../functional/config.ini.in | 2 +- .../functional}/create_cache.py | 2 +- .../functional}/decodescript.py | 0 .../functional}/dip3-deterministicmns.py | 0 .../functional}/dip4-coinbasemerkleroots.py | 0 .../functional}/disablewallet.py | 0 .../functional}/forknotify.py | 0 .../functional}/fundrawtransaction-hd.py | 0 .../functional}/fundrawtransaction.py | 0 .../functional}/getblocktemplate_longpoll.py | 0 .../functional}/getblocktemplate_proposals.py | 0 .../functional}/getchaintips.py | 0 .../functional}/httpbasics.py | 0 .../functional}/import-rescan.py | 0 .../functional}/importmulti.py | 0 .../functional}/importprunedfunds.py | 0 .../functional}/invalidateblock.py | 0 .../functional}/invalidblockrequest.py | 0 .../functional}/invalidtxrequest.py | 0 .../functional}/keypool-hd.py | 0 {qa/rpc-tests => test/functional}/keypool.py | 0 .../functional}/listsinceblock.py | 0 .../functional}/listtransactions.py | 0 .../functional}/llmq-chainlocks.py | 0 .../functional}/llmq-dkgerrors.py | 0 .../functional}/llmq-is-cl-conflicts.py | 0 .../functional}/llmq-signing.py | 0 .../functional}/llmq-simplepose.py | 0 .../functional}/maxblocksinflight.py | 0 .../functional}/maxuploadtarget.py | 0 .../functional}/mempool_limit.py | 0 .../functional}/mempool_packages.py | 0 .../functional}/mempool_reorg.py | 0 .../functional}/mempool_resurrect_test.py | 0 .../functional}/mempool_spendcoinbase.py | 0 .../functional}/merkle_blocks.py | 0 .../functional}/multi_rpc.py | 0 .../functional}/multikeysporks.py | 0 .../functional}/nodehandling.py | 0 .../functional}/nulldummy.py | 0 .../functional}/p2p-acceptblock.py | 0 .../functional}/p2p-autoinstantsend.py | 0 .../functional}/p2p-compactblocks.py | 0 .../functional}/p2p-fingerprint.py | 0 .../functional}/p2p-fullblocktest.py | 0 .../functional}/p2p-instantsend.py | 0 .../functional}/p2p-leaktests.py | 0 .../functional}/p2p-mempool.py | 0 .../functional}/p2p-timeouts.py | 0 .../functional}/p2p-versionbits-warning.py | 0 .../functional}/preciousblock.py | 0 .../functional}/prioritise_transaction.py | 0 .../functional}/proxy_test.py | 0 {qa/rpc-tests => test/functional}/pruning.py | 0 .../functional}/rawtransactions.py | 0 .../functional}/receivedby.py | 0 {qa/rpc-tests => test/functional}/reindex.py | 0 {qa/rpc-tests => test/functional}/rest.py | 0 .../functional}/rpcbind_test.py | 0 .../functional}/rpcnamedargs.py | 0 .../functional}/sendheaders.py | 0 .../functional}/signmessages.py | 0 .../functional}/signrawtransactions.py | 0 .../functional}/smartfees.py | 0 .../functional}/spentindex.py | 0 {qa/rpc-tests => test/functional}/sporks.py | 0 .../functional}/test_framework/__init__.py | 0 .../functional}/test_framework/authproxy.py | 0 .../functional}/test_framework/bignum.py | 0 .../functional}/test_framework/blockstore.py | 0 .../functional}/test_framework/blocktools.py | 0 .../functional}/test_framework/comptool.py | 0 .../functional}/test_framework/coverage.py | 0 .../functional}/test_framework/key.py | 0 .../functional}/test_framework/mininode.py | 0 .../functional}/test_framework/netutil.py | 0 .../functional}/test_framework/script.py | 0 .../functional}/test_framework/siphash.py | 0 .../functional}/test_framework/socks5.py | 0 .../test_framework/test_framework.py | 0 .../functional}/test_framework/util.py | 0 .../functional/test_runner.py | 37 ++++--- .../functional}/timestampindex.py | 0 {qa/rpc-tests => test/functional}/txindex.py | 0 .../functional}/txn_clone.py | 0 .../functional}/txn_doublespend.py | 0 .../functional}/wallet-accounts.py | 0 .../functional}/wallet-dump.py | 0 .../functional}/wallet-hd.py | 0 {qa/rpc-tests => test/functional}/wallet.py | 0 .../functional}/walletbackup.py | 0 .../functional}/zapwallettxes.py | 0 {qa/rpc-tests => test/functional}/zmq_test.py | 0 {src/test => test/util}/bctest.py | 6 +- test/util/bitcoin-util-test.py | 36 +++++++ test/util/buildenv.py.in | 4 + .../util}/data/bitcoin-util-test.json | 0 {src/test => test/util}/data/blanktxv1.hex | 0 {src/test => test/util}/data/blanktxv1.json | 0 {src/test => test/util}/data/blanktxv2.hex | 0 {src/test => test/util}/data/blanktxv2.json | 0 .../test => test/util}/data/tt-delin1-out.hex | 0 .../util}/data/tt-delin1-out.json | 0 .../util}/data/tt-delout1-out.hex | 0 .../util}/data/tt-delout1-out.json | 0 .../util}/data/tt-locktime317000-out.hex | 0 .../util}/data/tt-locktime317000-out.json | 0 {src/test => test/util}/data/tx394b54bb.hex | 0 {src/test => test/util}/data/txcreate1.hex | 0 {src/test => test/util}/data/txcreate1.json | 0 {src/test => test/util}/data/txcreate2.hex | 0 {src/test => test/util}/data/txcreate2.json | 0 .../test => test/util}/data/txcreatedata1.hex | 0 .../util}/data/txcreatedata1.json | 0 .../test => test/util}/data/txcreatedata2.hex | 0 .../util}/data/txcreatedata2.json | 0 .../util}/data/txcreatedata_seq0.hex | 0 .../util}/data/txcreatedata_seq0.json | 0 .../util}/data/txcreatedata_seq1.hex | 0 .../util}/data/txcreatedata_seq1.json | 0 .../util}/data/txcreatemultisig1.hex | 0 .../util}/data/txcreatemultisig1.json | 0 .../util}/data/txcreatemultisig2.hex | 0 .../util}/data/txcreatemultisig2.json | 0 .../util}/data/txcreateoutpubkey1.hex | 0 .../util}/data/txcreateoutpubkey1.json | 0 .../util}/data/txcreatescript1.hex | 0 .../util}/data/txcreatescript1.json | 0 .../util}/data/txcreatescript2.hex | 0 .../util}/data/txcreatescript2.json | 0 .../util}/data/txcreatesignv1.hex | 0 .../util}/data/txcreatesignv1.json | 0 .../util}/data/txcreatesignv2.hex | 0 160 files changed, 239 insertions(+), 245 deletions(-) delete mode 100644 qa/README.md delete mode 100755 src/test/bitcoin-util-test.py delete mode 100644 src/test/buildenv.py.in create mode 100644 test/README.md rename {qa/rpc-tests => test/functional}/.gitignore (100%) rename {qa/rpc-tests => test/functional}/README.md (100%) rename {qa/rpc-tests => test/functional}/abandonconflict.py (100%) rename {qa/rpc-tests => test/functional}/addressindex.py (100%) rename {qa/rpc-tests => test/functional}/assumevalid.py (100%) rename {qa/rpc-tests => test/functional}/autois-mempool.py (100%) rename {qa/rpc-tests => test/functional}/bip65-cltv-p2p.py (100%) rename {qa/rpc-tests => test/functional}/bip65-cltv.py (100%) rename {qa/rpc-tests => test/functional}/bip68-112-113-p2p.py (100%) rename {qa/rpc-tests => test/functional}/bip68-sequence.py (100%) rename {qa/rpc-tests => test/functional}/bip9-softforks.py (100%) rename {qa/rpc-tests => test/functional}/bipdersig-p2p.py (100%) rename {qa/rpc-tests => test/functional}/bipdersig.py (100%) rename {qa/rpc-tests => test/functional}/blockchain.py (100%) rename qa/pull-tester/tests_config.ini.in => test/functional/config.ini.in (95%) rename {qa/rpc-tests => test/functional}/create_cache.py (89%) rename {qa/rpc-tests => test/functional}/decodescript.py (100%) rename {qa/rpc-tests => test/functional}/dip3-deterministicmns.py (100%) rename {qa/rpc-tests => test/functional}/dip4-coinbasemerkleroots.py (100%) rename {qa/rpc-tests => test/functional}/disablewallet.py (100%) rename {qa/rpc-tests => test/functional}/forknotify.py (100%) rename {qa/rpc-tests => test/functional}/fundrawtransaction-hd.py (100%) rename {qa/rpc-tests => test/functional}/fundrawtransaction.py (100%) rename {qa/rpc-tests => test/functional}/getblocktemplate_longpoll.py (100%) rename {qa/rpc-tests => test/functional}/getblocktemplate_proposals.py (100%) rename {qa/rpc-tests => test/functional}/getchaintips.py (100%) rename {qa/rpc-tests => test/functional}/httpbasics.py (100%) rename {qa/rpc-tests => test/functional}/import-rescan.py (100%) rename {qa/rpc-tests => test/functional}/importmulti.py (100%) rename {qa/rpc-tests => test/functional}/importprunedfunds.py (100%) rename {qa/rpc-tests => test/functional}/invalidateblock.py (100%) rename {qa/rpc-tests => test/functional}/invalidblockrequest.py (100%) rename {qa/rpc-tests => test/functional}/invalidtxrequest.py (100%) rename {qa/rpc-tests => test/functional}/keypool-hd.py (100%) rename {qa/rpc-tests => test/functional}/keypool.py (100%) rename {qa/rpc-tests => test/functional}/listsinceblock.py (100%) rename {qa/rpc-tests => test/functional}/listtransactions.py (100%) rename {qa/rpc-tests => test/functional}/llmq-chainlocks.py (100%) rename {qa/rpc-tests => test/functional}/llmq-dkgerrors.py (100%) rename {qa/rpc-tests => test/functional}/llmq-is-cl-conflicts.py (100%) rename {qa/rpc-tests => test/functional}/llmq-signing.py (100%) rename {qa/rpc-tests => test/functional}/llmq-simplepose.py (100%) rename {qa/rpc-tests => test/functional}/maxblocksinflight.py (100%) rename {qa/rpc-tests => test/functional}/maxuploadtarget.py (100%) rename {qa/rpc-tests => test/functional}/mempool_limit.py (100%) rename {qa/rpc-tests => test/functional}/mempool_packages.py (100%) rename {qa/rpc-tests => test/functional}/mempool_reorg.py (100%) rename {qa/rpc-tests => test/functional}/mempool_resurrect_test.py (100%) rename {qa/rpc-tests => test/functional}/mempool_spendcoinbase.py (100%) rename {qa/rpc-tests => test/functional}/merkle_blocks.py (100%) rename {qa/rpc-tests => test/functional}/multi_rpc.py (100%) rename {qa/rpc-tests => test/functional}/multikeysporks.py (100%) rename {qa/rpc-tests => test/functional}/nodehandling.py (100%) rename {qa/rpc-tests => test/functional}/nulldummy.py (100%) rename {qa/rpc-tests => test/functional}/p2p-acceptblock.py (100%) rename {qa/rpc-tests => test/functional}/p2p-autoinstantsend.py (100%) rename {qa/rpc-tests => test/functional}/p2p-compactblocks.py (100%) rename {qa/rpc-tests => test/functional}/p2p-fingerprint.py (100%) rename {qa/rpc-tests => test/functional}/p2p-fullblocktest.py (100%) rename {qa/rpc-tests => test/functional}/p2p-instantsend.py (100%) rename {qa/rpc-tests => test/functional}/p2p-leaktests.py (100%) rename {qa/rpc-tests => test/functional}/p2p-mempool.py (100%) rename {qa/rpc-tests => test/functional}/p2p-timeouts.py (100%) rename {qa/rpc-tests => test/functional}/p2p-versionbits-warning.py (100%) rename {qa/rpc-tests => test/functional}/preciousblock.py (100%) rename {qa/rpc-tests => test/functional}/prioritise_transaction.py (100%) rename {qa/rpc-tests => test/functional}/proxy_test.py (100%) rename {qa/rpc-tests => test/functional}/pruning.py (100%) rename {qa/rpc-tests => test/functional}/rawtransactions.py (100%) rename {qa/rpc-tests => test/functional}/receivedby.py (100%) rename {qa/rpc-tests => test/functional}/reindex.py (100%) rename {qa/rpc-tests => test/functional}/rest.py (100%) rename {qa/rpc-tests => test/functional}/rpcbind_test.py (100%) rename {qa/rpc-tests => test/functional}/rpcnamedargs.py (100%) rename {qa/rpc-tests => test/functional}/sendheaders.py (100%) rename {qa/rpc-tests => test/functional}/signmessages.py (100%) rename {qa/rpc-tests => test/functional}/signrawtransactions.py (100%) rename {qa/rpc-tests => test/functional}/smartfees.py (100%) rename {qa/rpc-tests => test/functional}/spentindex.py (100%) rename {qa/rpc-tests => test/functional}/sporks.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/__init__.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/authproxy.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/bignum.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/blockstore.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/blocktools.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/comptool.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/coverage.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/key.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/mininode.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/netutil.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/script.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/siphash.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/socks5.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/test_framework.py (100%) rename {qa/rpc-tests => test/functional}/test_framework/util.py (100%) rename qa/pull-tester/rpc-tests.py => test/functional/test_runner.py (92%) rename {qa/rpc-tests => test/functional}/timestampindex.py (100%) rename {qa/rpc-tests => test/functional}/txindex.py (100%) rename {qa/rpc-tests => test/functional}/txn_clone.py (100%) rename {qa/rpc-tests => test/functional}/txn_doublespend.py (100%) rename {qa/rpc-tests => test/functional}/wallet-accounts.py (100%) rename {qa/rpc-tests => test/functional}/wallet-dump.py (100%) rename {qa/rpc-tests => test/functional}/wallet-hd.py (100%) rename {qa/rpc-tests => test/functional}/wallet.py (100%) rename {qa/rpc-tests => test/functional}/walletbackup.py (100%) rename {qa/rpc-tests => test/functional}/zapwallettxes.py (100%) rename {qa/rpc-tests => test/functional}/zmq_test.py (100%) rename {src/test => test/util}/bctest.py (96%) create mode 100755 test/util/bitcoin-util-test.py create mode 100644 test/util/buildenv.py.in rename {src/test => test/util}/data/bitcoin-util-test.json (100%) rename {src/test => test/util}/data/blanktxv1.hex (100%) rename {src/test => test/util}/data/blanktxv1.json (100%) rename {src/test => test/util}/data/blanktxv2.hex (100%) rename {src/test => test/util}/data/blanktxv2.json (100%) rename {src/test => test/util}/data/tt-delin1-out.hex (100%) rename {src/test => test/util}/data/tt-delin1-out.json (100%) rename {src/test => test/util}/data/tt-delout1-out.hex (100%) rename {src/test => test/util}/data/tt-delout1-out.json (100%) rename {src/test => test/util}/data/tt-locktime317000-out.hex (100%) rename {src/test => test/util}/data/tt-locktime317000-out.json (100%) rename {src/test => test/util}/data/tx394b54bb.hex (100%) rename {src/test => test/util}/data/txcreate1.hex (100%) rename {src/test => test/util}/data/txcreate1.json (100%) rename {src/test => test/util}/data/txcreate2.hex (100%) rename {src/test => test/util}/data/txcreate2.json (100%) rename {src/test => test/util}/data/txcreatedata1.hex (100%) rename {src/test => test/util}/data/txcreatedata1.json (100%) rename {src/test => test/util}/data/txcreatedata2.hex (100%) rename {src/test => test/util}/data/txcreatedata2.json (100%) rename {src/test => test/util}/data/txcreatedata_seq0.hex (100%) rename {src/test => test/util}/data/txcreatedata_seq0.json (100%) rename {src/test => test/util}/data/txcreatedata_seq1.hex (100%) rename {src/test => test/util}/data/txcreatedata_seq1.json (100%) rename {src/test => test/util}/data/txcreatemultisig1.hex (100%) rename {src/test => test/util}/data/txcreatemultisig1.json (100%) rename {src/test => test/util}/data/txcreatemultisig2.hex (100%) rename {src/test => test/util}/data/txcreatemultisig2.json (100%) rename {src/test => test/util}/data/txcreateoutpubkey1.hex (100%) rename {src/test => test/util}/data/txcreateoutpubkey1.json (100%) rename {src/test => test/util}/data/txcreatescript1.hex (100%) rename {src/test => test/util}/data/txcreatescript1.json (100%) rename {src/test => test/util}/data/txcreatescript2.hex (100%) rename {src/test => test/util}/data/txcreatescript2.json (100%) rename {src/test => test/util}/data/txcreatesignv1.hex (100%) rename {src/test => test/util}/data/txcreatesignv1.json (100%) rename {src/test => test/util}/data/txcreatesignv2.hex (100%) diff --git a/.gitignore b/.gitignore index d34b5eb02a3e..c3be44a72c15 100644 --- a/.gitignore +++ b/.gitignore @@ -108,9 +108,9 @@ coverage_percent.txt linux-coverage-build linux-build win32-build -qa/pull-tester/tests_config.py -qa/pull-tester/tests_config.ini -qa/cache/* +test/functional/config.ini +test/util/buildenv.py +test/cache/* !src/leveldb*/Makefile diff --git a/Makefile.am b/Makefile.am index ce09ef59eaf9..12a48f61fcd6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,7 +61,7 @@ OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) \ COVERAGE_INFO = baseline_filtered_combined.info baseline.info \ leveldb_baseline.info test_dash_filtered.info total_coverage.info \ - baseline_filtered.info rpc_test.info rpc_test_filtered.info \ + baseline_filtered.info functional_test.info functional_test_filtered.info \ leveldb_baseline_filtered.info test_dash_coverage.info test_dash.info dist-hook: @@ -191,20 +191,20 @@ test_dash.info: baseline_filtered_combined.info test_dash_filtered.info: test_dash.info $(LCOV) -r $< "/usr/include/*" -o $@ -rpc_test.info: test_dash_filtered.info - -@TIMEOUT=15 python qa/pull-tester/rpc-tests.py $(EXTENDED_RPC_TESTS) - $(LCOV) -c -d $(abs_builddir)/src --t rpc-tests -o $@ +functional_test.info: test_dash_filtered.info + -@TIMEOUT=15 python test/functional/test_runner.py $(EXTENDED_FUNCTIONAL_TESTS) + $(LCOV) -c -d $(abs_builddir)/src --t functional-tests -o $@ $(LCOV) -z -d $(abs_builddir)/src $(LCOV) -z -d $(abs_builddir)/src/leveldb -rpc_test_filtered.info: rpc_test.info +functional_test_filtered.info: functional_test.info $(LCOV) -r $< "/usr/include/*" -o $@ test_dash_coverage.info: baseline_filtered_combined.info test_dash_filtered.info $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_dash_filtered.info -o $@ -total_coverage.info: baseline_filtered_combined.info test_dash_filtered.info rpc_test_filtered.info - $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_dash_filtered.info -a rpc_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt +total_coverage.info: baseline_filtered_combined.info test_dash_filtered.info functional_test_filtered.info + $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_dash_filtered.info -a functional_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt test_dash.coverage/.dirstamp: test_dash_coverage.info $(GENHTML) -s $< -o $(@D) @@ -220,14 +220,58 @@ endif dist_noinst_SCRIPTS = autogen.sh -EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc-tests $(DIST_CONTRIB) $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) $(BIN_CHECKS) +EXTRA_DIST = $(top_srcdir)/share/genbuild.sh test/functional/test_runner.py test/functional $(DIST_CONTRIB) $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) $(BIN_CHECKS) + +EXTRA_DIST += \ + test/util/bctest.py \ + test/util/bitcoin-util-test.py \ + test/util/data/bitcoin-util-test.json \ + test/util/data/blanktxv1.hex \ + test/util/data/blanktxv1.json \ + test/util/data/blanktxv2.hex \ + test/util/data/blanktxv2.json \ + test/util/data/tt-delin1-out.hex \ + test/util/data/tt-delin1-out.json \ + test/util/data/tt-delout1-out.hex \ + test/util/data/tt-delout1-out.json \ + test/util/data/tt-locktime317000-out.hex \ + test/util/data/tt-locktime317000-out.json \ + test/util/data/tx394b54bb.hex \ + test/util/data/txcreate1.hex \ + test/util/data/txcreate1.json \ + test/util/data/txcreate2.hex \ + test/util/data/txcreate2.json \ + test/util/data/txcreatedata1.hex \ + test/util/data/txcreatedata1.json \ + test/util/data/txcreatedata2.hex \ + test/util/data/txcreatedata2.json \ + test/util/data/txcreatedata_seq0.hex \ + test/util/data/txcreatedata_seq0.json \ + test/util/data/txcreatedata_seq1.hex \ + test/util/data/txcreatedata_seq1.json \ + test/util/data/txcreatemultisig1.hex \ + test/util/data/txcreatemultisig1.json \ + test/util/data/txcreatemultisig2.hex \ + test/util/data/txcreatemultisig2.json \ + test/util/data/txcreateoutpubkey1.hex \ + test/util/data/txcreateoutpubkey1.json \ + test/util/data/txcreatescript1.hex \ + test/util/data/txcreatescript1.json \ + test/util/data/txcreatescript2.hex \ + test/util/data/txcreatescript2.json \ + test/util/data/txcreatesignv1.hex \ + test/util/data/txcreatesignv1.json \ + test/util/data/txcreatesignv2.hex CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) +# This file is problematic for out-of-tree builds if it exists. +DISTCLEANFILES = test/util/buildenv.pyc + .INTERMEDIATE: $(COVERAGE_INFO) DISTCHECK_CONFIGURE_FLAGS = --enable-man clean-local: - rm -rf coverage_percent.txt test_dash.coverage/ total.coverage/ qa/tmp/ cache/ $(OSX_APP) - rm -rf qa/pull-tester/__pycache__ + rm -rf coverage_percent.txt test_dash.coverage/ total.coverage/ test/tmp/ cache/ $(OSX_APP) + rm -rf test/functional/__pycache__ diff --git a/README.md b/README.md index d73b9895996b..0f7407932071 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,9 @@ submit new unit tests for old code. Unit tests can be compiled and run (assuming they weren't disabled in configure) with: `make check`. Further details on running and extending unit tests can be found in [/src/test/README.md](/src/test/README.md). -There are also [regression and integration tests](/qa) of the RPC interface, written +There are also [regression and integration tests](/test), written in Python, that are run automatically on the build server. -These tests can be run (if the [test dependencies](/qa) are installed) with: `qa/pull-tester/rpc-tests.py` +These tests can be run (if the [test dependencies](/test) are installed) with: `test/functional/test_runner.py` The Travis CI system makes sure that every pull request is built for Windows, Linux, and OS X, and that unit/sanity tests are run automatically. diff --git a/ci/test_integrationtests.sh b/ci/test_integrationtests.sh index 7b3573961919..0edc9d651371 100755 --- a/ci/test_integrationtests.sh +++ b/ci/test_integrationtests.sh @@ -17,4 +17,4 @@ export LD_LIBRARY_PATH=$BUILD_DIR/depends/$HOST/lib cd build-ci/dashcore-$BUILD_TARGET -./qa/pull-tester/rpc-tests.py --coverage $PASS_ARGS +./test/functional/test_runner.py --coverage $PASS_ARGS diff --git a/configure.ac b/configure.ac index a67e0950e8a7..bacf8d3d21f8 100644 --- a/configure.ac +++ b/configure.ac @@ -124,10 +124,10 @@ AC_ARG_ENABLE(bench, [use_bench=$enableval], [use_bench=yes]) -AC_ARG_ENABLE([extended-rpc-tests], - AS_HELP_STRING([--enable-extended-rpc-tests],[enable expensive RPC tests when using lcov (default no)]), - [use_extended_rpc_tests=$enableval], - [use_extended_rpc_tests=no]) +AC_ARG_ENABLE([extended-functional-tests], + AS_HELP_STRING([--enable-extended-functional-tests],[enable expensive functional tests when using lcov (default no)]), + [use_extended_functional_tests=$enableval], + [use_extended_functional_tests=no]) AC_ARG_WITH([qrencode], [AS_HELP_STRING([--with-qrencode], @@ -459,8 +459,8 @@ if test x$use_pkgconfig = xyes; then ]) fi -if test x$use_extended_rpc_tests != xno; then - AC_SUBST(EXTENDED_RPC_TESTS, -extended) +if test x$use_extended_functional_tests != xno; then + AC_SUBST(EXTENDED_FUNCTIONAL_TESTS, --extended) fi if test x$use_lcov = xyes; then @@ -1200,10 +1200,12 @@ AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) AC_SUBST(PROTOBUF_LIBS) AC_SUBST(QR_LIBS) -AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py]) -AC_CONFIG_FILES([qa/pull-tester/tests_config.ini],[chmod +x qa/pull-tester/tests_config.ini]) +AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/functional/config.ini]) +AC_CONFIG_FILES([test/util/buildenv.py],[chmod +x test/util/buildenv.py]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) -AC_CONFIG_LINKS([qa/pull-tester/rpc-tests.py:qa/pull-tester/rpc-tests.py]) +AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py]) +AC_CONFIG_LINKS([test/util/bitcoin-util-test.py:test/util/bitcoin-util-test.py]) +AC_CONFIG_LINKS([test/util/bctest.py:test/util/bctest.py]) dnl boost's m4 checks do something really nasty: they export these vars. As a dnl result, they leak into secp256k1's configure and crazy things happen. @@ -1251,8 +1253,8 @@ esac dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows case ${OS} in *Windows*) - sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' qa/pull-tester/tests_config.py > qa/pull-tester/tests_config-2.py - mv qa/pull-tester/tests_config-2.py qa/pull-tester/tests_config.py + sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' test/functional/config.ini > test/functional/config-2.ini + mv test/functional/config-2.ini test/functional/config.ini ;; esac diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py index 2444d5dd8180..ac518d2dfa1a 100755 --- a/contrib/devtools/copyright_header.py +++ b/contrib/devtools/copyright_header.py @@ -33,7 +33,7 @@ 'src/tinyformat.h', 'src/leveldb/util/env_win.cc', 'src/crypto/ctaes/bench.c', - 'qa/rpc-tests/test_framework/bignum.py', + 'test/functional/test_framework/bignum.py', # python init: '*__init__.py', ] diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 0231cbeab493..003ecb4948b9 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -133,7 +133,7 @@ Run with the -testnet option to run with "play coins" on the test network, if yo are testing multi-machine code that needs to operate across the internet. If you are testing something that can run on one machine, run with the -regtest option. -In regression test mode, blocks can be created on-demand; see qa/rpc-tests/ for tests +In regression test mode, blocks can be created on-demand; see test/functional/ for tests that run in -regtest mode. **DEBUG_LOCKORDER** @@ -255,7 +255,7 @@ Wallet - *Rationale*: In RPC code that conditionally uses the wallet (such as `validateaddress`) it is easy to forget that global pointer `pwalletMain` - can be NULL. See `qa/rpc-tests/disablewallet.py` for functional tests + can be NULL. See `test/functional/disablewallet.py` for functional tests exercising the API with `-disablewallet` - Include `db_cxx.h` (BerkeleyDB header) only when `ENABLE_WALLET` is set diff --git a/qa/README.md b/qa/README.md deleted file mode 100644 index 0f66a85813a2..000000000000 --- a/qa/README.md +++ /dev/null @@ -1,87 +0,0 @@ -The [pull-tester](/qa/pull-tester/) folder contains a script to call -multiple tests from the [rpc-tests](/qa/rpc-tests/) folder. - -Every pull request to the Dash Core repository is built and run through -the regression test suite. You can also run all or only individual -tests locally. - -Test dependencies -================= -Before running the tests, the following must be installed. - -Unix ----- -The python3-zmq library is required. On Ubuntu or Debian it can be installed via: -``` -sudo apt-get install python3-zmq -``` - -OS X ------- -``` -pip3 install pyzmq -``` - -Running tests -============= - -You can run any single test by calling - - qa/pull-tester/rpc-tests.py - -Or you can run any combination of tests by calling - - qa/pull-tester/rpc-tests.py ... - -Run the regression test suite with - - qa/pull-tester/rpc-tests.py - -Run all possible tests with - - qa/pull-tester/rpc-tests.py --extended - -By default, tests will be run in parallel. To specify how many jobs to run, -append `--jobs=n` (default n=4). - -If you want to create a basic coverage report for the RPC test suite, append `--coverage`. - -Possible options, which apply to each individual test run: - -``` - -h, --help show this help message and exit - --nocleanup Leave dashds and test.* datadir on exit or error - --noshutdown Don't stop dashds after the test execution - --srcdir=SRCDIR Source directory containing dashd/dash-cli - (default: ../../src) - --tmpdir=TMPDIR Root directory for datadirs - --tracerpc Print out all RPC calls as they are made - --coveragedir=COVERAGEDIR - Write tested RPC commands into this directory -``` - -If you set the environment variable `PYTHON_DEBUG=1` you will get some debug -output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.py wallet`). - -A 200-block -regtest blockchain and wallets for four nodes -is created the first time a regression test is run and -is stored in the cache/ directory. Each node has 25 mature -blocks (25*500=12500 DASH) in its wallet. - -After the first run, the cache/ blockchain and wallets are -copied into a temporary directory and used as the initial -test state. - -If you get into a bad state, you should be able -to recover with: - -```bash -rm -rf cache -killall dashd -``` - -Writing tests -============= -You are encouraged to write tests for new or existing features. -Further information about the test framework and individual RPC -tests is found in [qa/rpc-tests](/qa/rpc-tests). diff --git a/src/Makefile.test.include b/src/Makefile.test.include index cd56343a29c3..75ec2f683198 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -8,48 +8,6 @@ bin_PROGRAMS += test/test_dash TEST_SRCDIR = test TEST_BINARY=test/test_dash$(EXEEXT) - -EXTRA_DIST += \ - test/bctest.py \ - test/bitcoin-util-test.py \ - test/data/bitcoin-util-test.json \ - test/data/blanktxv1.hex \ - test/data/blanktxv1.json \ - test/data/blanktxv2.hex \ - test/data/blanktxv2.json \ - test/data/tt-delin1-out.hex \ - test/data/tt-delin1-out.json \ - test/data/tt-delout1-out.hex \ - test/data/tt-delout1-out.json \ - test/data/tt-locktime317000-out.hex \ - test/data/tt-locktime317000-out.json \ - test/data/tx394b54bb.hex \ - test/data/txcreate1.hex \ - test/data/txcreate1.json \ - test/data/txcreate2.hex \ - test/data/txcreate2.json \ - test/data/txcreatedata1.hex \ - test/data/txcreatedata1.json \ - test/data/txcreatedata2.hex \ - test/data/txcreatedata2.json \ - test/data/txcreatedata_seq0.hex \ - test/data/txcreatedata_seq0.json \ - test/data/txcreatedata_seq1.hex \ - test/data/txcreatedata_seq1.json \ - test/data/txcreatemultisig1.hex \ - test/data/txcreatemultisig1.json \ - test/data/txcreatemultisig2.hex \ - test/data/txcreatemultisig2.json \ - test/data/txcreateoutpubkey1.hex \ - test/data/txcreateoutpubkey1.json \ - test/data/txcreatescript1.hex \ - test/data/txcreatescript1.json \ - test/data/txcreatescript2.hex \ - test/data/txcreatescript2.json \ - test/data/txcreatesignv1.hex \ - test/data/txcreatesignv1.json \ - test/data/txcreatesignv2.hex - JSON_TEST_FILES = \ test/data/script_tests.json \ test/data/base58_keys_valid.json \ @@ -174,9 +132,6 @@ CLEAN_BITCOIN_TEST = test/*.gcda test/*.gcno $(GENERATED_TEST_FILES) CLEANFILES += $(CLEAN_BITCOIN_TEST) -# This file is problematic for out-of-tree builds if it exists. -DISTCLEANFILES += test/buildenv.pyc - dash_test: $(TEST_BINARY) dash_test_check: $(TEST_BINARY) FORCE @@ -186,8 +141,8 @@ dash_test_clean : FORCE rm -f $(CLEAN_BITCOIN_TEST) $(test_test_dash_OBJECTS) $(TEST_BINARY) check-local: - @echo "Running test/bitcoin-util-test.py..." - $(AM_V_at)srcdir=$(srcdir) PYTHONPATH=$(builddir)/test $(PYTHON) $(srcdir)/test/bitcoin-util-test.py + @echo "Running test/util/bitcoin-util-test.py..." + $(PYTHON) $(top_builddir)/test/util/bitcoin-util-test.py $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check if EMBEDDED_UNIVALUE $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check diff --git a/src/test/README.md b/src/test/README.md index 69f1251a8265..b7cc9608724e 100644 --- a/src/test/README.md +++ b/src/test/README.md @@ -39,7 +39,7 @@ unit tests as possible). The build system is setup to compile an executable called `test_dash` that runs all of the unit tests. The main source file is called -test_dash.cpp. To add a new unit test file to our test suite you need +test_dash.cpp. To add a new unit test file to our test suite you need to add the file to `src/Makefile.test.include`. The pattern is to create one test file for each class or source file for which you want to create unit tests. The file naming convention is `_tests.cpp` @@ -50,12 +50,3 @@ examine `uint256_tests.cpp`. For further reading, I found the following website to be helpful in explaining how the boost unit test framework works: [http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/](http://www.alittlemadness.com/2009/03/31/c-unit-testing-with-boosttest/). - -### bitcoin-util-test.py - -The test directory also contains the bitcoin-util-test.py tool, which tests bitcoin utils (currently just dash-tx). This test gets run automatically during the `make check` build process. It is also possible to run the test manually from the src directory: - -``` -test/bitcoin-util-test.py --srcdir=[current directory] - -``` \ No newline at end of file diff --git a/src/test/bitcoin-util-test.py b/src/test/bitcoin-util-test.py deleted file mode 100755 index e2087187aaba..000000000000 --- a/src/test/bitcoin-util-test.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -# Copyright 2014 BitPay Inc. -# Copyright 2016 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -from __future__ import division,print_function,unicode_literals -import os -import bctest -import buildenv -import argparse -import logging - -help_text="""Test framework for bitcoin utils. - -Runs automatically during `make check`. - -Can also be run manually from the src directory by specifying the source directory: - -test/bitcoin-util-test.py --srcdir='srcdir' [--verbose] -""" - -if __name__ == '__main__': - # Try to get the source directory from the environment variables. This will - # be set for `make check` automated runs. If environment variable is not set, - # then get the source directory from command line args. - try: - srcdir = os.environ["srcdir"] - verbose = False - except: - parser = argparse.ArgumentParser(description=help_text) - parser.add_argument('-s', '--srcdir') - parser.add_argument('-v', '--verbose', action='store_true') - args = parser.parse_args() - srcdir = args.srcdir - verbose = args.verbose - - if verbose: - level = logging.DEBUG - else: - level = logging.ERROR - formatter = '%(asctime)s - %(levelname)s - %(message)s' - # Add the format/level to the logger - logging.basicConfig(format = formatter, level=level) - - bctest.bctester(srcdir + "/test/data", "bitcoin-util-test.json", buildenv) diff --git a/src/test/buildenv.py.in b/src/test/buildenv.py.in deleted file mode 100644 index 153f34a3dbc7..000000000000 --- a/src/test/buildenv.py.in +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python -exeext="@EXEEXT@" diff --git a/test/README.md b/test/README.md new file mode 100644 index 000000000000..aaaa0406c4fb --- /dev/null +++ b/test/README.md @@ -0,0 +1,97 @@ +This directory contains integration tests that test dashd and its +utilities in their entirety. It does not contain unit tests, which +can be found in [/src/test](/src/test), [/src/wallet/test](/src/wallet/test), +etc. + +There are currently two sets of tests in this directory: + +- [functional](/test/functional) which test the functionality of +dashd and dash-qt by interacting with them through the RPC and P2P +interfaces. +- [util](test/util) which tests the dash utilities, currently only +dash-tx. + +The util tests are run as part of `make check` target. The functional +tests are run by the travis continuous build process whenever a pull +request is opened. Both sets of tests can also be run locally. + +Functional Test dependencies +============================ +The ZMQ functional test requires a python ZMQ library. To install it: + +- on Unix, run `sudo apt-get install python3-zmq` +- on mac OS, run `pip3 install pyzmq` + +Running tests locally +===================== + +Functional tests +---------------- + +You can run any single test by calling + + test/functional/test_runner.py + +Or you can run any combination of tests by calling + + test/functional/test_runner.py ... + +Run the regression test suite with + + test/functional/test_runner.py + +Run all possible tests with + + test/functional/test_runner.py --extended + +By default, tests will be run in parallel. To specify how many jobs to run, +append `--jobs=n` (default n=4). + +If you want to create a basic coverage report for the RPC test suite, append `--coverage`. + +Possible options, which apply to each individual test run: + +``` + -h, --help show this help message and exit + --nocleanup Leave dashds and test.* datadir on exit or error + --noshutdown Don't stop dashds after the test execution + --srcdir=SRCDIR Source directory containing dashd/dash-cli + (default: ../../src) + --tmpdir=TMPDIR Root directory for datadirs + --tracerpc Print out all RPC calls as they are made + --coveragedir=COVERAGEDIR + Write tested RPC commands into this directory +``` + +If you set the environment variable `PYTHON_DEBUG=1` you will get some debug +output (example: `PYTHON_DEBUG=1 test/functional/test_runner.py wallet`). + +A 200-block -regtest blockchain and wallets for four nodes +is created the first time a regression test is run and +is stored in the cache/ directory. Each node has 25 mature +blocks (25*500=12500 DASH) in its wallet. + +After the first run, the cache/ blockchain and wallets are +copied into a temporary directory and used as the initial +test state. + +If you get into a bad state, you should be able +to recover with: + +```bash +rm -rf cache +killall dashd +``` + +Util tests +---------- + +Util tests can be run locally by running `test/util/bitcoin-util-test.py`. +Use the `-v` option for verbose output. + +Writing functional tests +======================== + +You are encouraged to write functional tests for new or existing features. +Further information about the functional test framework and individual +tests is found in [test/functional](/test/functional). diff --git a/qa/rpc-tests/.gitignore b/test/functional/.gitignore similarity index 100% rename from qa/rpc-tests/.gitignore rename to test/functional/.gitignore diff --git a/qa/rpc-tests/README.md b/test/functional/README.md similarity index 100% rename from qa/rpc-tests/README.md rename to test/functional/README.md diff --git a/qa/rpc-tests/abandonconflict.py b/test/functional/abandonconflict.py similarity index 100% rename from qa/rpc-tests/abandonconflict.py rename to test/functional/abandonconflict.py diff --git a/qa/rpc-tests/addressindex.py b/test/functional/addressindex.py similarity index 100% rename from qa/rpc-tests/addressindex.py rename to test/functional/addressindex.py diff --git a/qa/rpc-tests/assumevalid.py b/test/functional/assumevalid.py similarity index 100% rename from qa/rpc-tests/assumevalid.py rename to test/functional/assumevalid.py diff --git a/qa/rpc-tests/autois-mempool.py b/test/functional/autois-mempool.py similarity index 100% rename from qa/rpc-tests/autois-mempool.py rename to test/functional/autois-mempool.py diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/test/functional/bip65-cltv-p2p.py similarity index 100% rename from qa/rpc-tests/bip65-cltv-p2p.py rename to test/functional/bip65-cltv-p2p.py diff --git a/qa/rpc-tests/bip65-cltv.py b/test/functional/bip65-cltv.py similarity index 100% rename from qa/rpc-tests/bip65-cltv.py rename to test/functional/bip65-cltv.py diff --git a/qa/rpc-tests/bip68-112-113-p2p.py b/test/functional/bip68-112-113-p2p.py similarity index 100% rename from qa/rpc-tests/bip68-112-113-p2p.py rename to test/functional/bip68-112-113-p2p.py diff --git a/qa/rpc-tests/bip68-sequence.py b/test/functional/bip68-sequence.py similarity index 100% rename from qa/rpc-tests/bip68-sequence.py rename to test/functional/bip68-sequence.py diff --git a/qa/rpc-tests/bip9-softforks.py b/test/functional/bip9-softforks.py similarity index 100% rename from qa/rpc-tests/bip9-softforks.py rename to test/functional/bip9-softforks.py diff --git a/qa/rpc-tests/bipdersig-p2p.py b/test/functional/bipdersig-p2p.py similarity index 100% rename from qa/rpc-tests/bipdersig-p2p.py rename to test/functional/bipdersig-p2p.py diff --git a/qa/rpc-tests/bipdersig.py b/test/functional/bipdersig.py similarity index 100% rename from qa/rpc-tests/bipdersig.py rename to test/functional/bipdersig.py diff --git a/qa/rpc-tests/blockchain.py b/test/functional/blockchain.py similarity index 100% rename from qa/rpc-tests/blockchain.py rename to test/functional/blockchain.py diff --git a/qa/pull-tester/tests_config.ini.in b/test/functional/config.ini.in similarity index 95% rename from qa/pull-tester/tests_config.ini.in rename to test/functional/config.ini.in index e3e457d0b1d1..29586c555d53 100644 --- a/qa/pull-tester/tests_config.ini.in +++ b/test/functional/config.ini.in @@ -3,7 +3,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # These environment variables are set by the build process and read by -# rpc-tests.py +# test/functional/test_runner.py [environment] SRCDIR=@abs_top_srcdir@ diff --git a/qa/rpc-tests/create_cache.py b/test/functional/create_cache.py similarity index 89% rename from qa/rpc-tests/create_cache.py rename to test/functional/create_cache.py index 13eac92bbce7..39c4c0f47edc 100755 --- a/qa/rpc-tests/create_cache.py +++ b/test/functional/create_cache.py @@ -5,7 +5,7 @@ """Create a blockchain cache. Creating a cache of the blockchain speeds up test execution when running -multiple qa tests. This helper script is executed by rpc-tests when multiple +multiple functional tests. This helper script is executed by test_runner when multiple tests are being run in parallel. """ diff --git a/qa/rpc-tests/decodescript.py b/test/functional/decodescript.py similarity index 100% rename from qa/rpc-tests/decodescript.py rename to test/functional/decodescript.py diff --git a/qa/rpc-tests/dip3-deterministicmns.py b/test/functional/dip3-deterministicmns.py similarity index 100% rename from qa/rpc-tests/dip3-deterministicmns.py rename to test/functional/dip3-deterministicmns.py diff --git a/qa/rpc-tests/dip4-coinbasemerkleroots.py b/test/functional/dip4-coinbasemerkleroots.py similarity index 100% rename from qa/rpc-tests/dip4-coinbasemerkleroots.py rename to test/functional/dip4-coinbasemerkleroots.py diff --git a/qa/rpc-tests/disablewallet.py b/test/functional/disablewallet.py similarity index 100% rename from qa/rpc-tests/disablewallet.py rename to test/functional/disablewallet.py diff --git a/qa/rpc-tests/forknotify.py b/test/functional/forknotify.py similarity index 100% rename from qa/rpc-tests/forknotify.py rename to test/functional/forknotify.py diff --git a/qa/rpc-tests/fundrawtransaction-hd.py b/test/functional/fundrawtransaction-hd.py similarity index 100% rename from qa/rpc-tests/fundrawtransaction-hd.py rename to test/functional/fundrawtransaction-hd.py diff --git a/qa/rpc-tests/fundrawtransaction.py b/test/functional/fundrawtransaction.py similarity index 100% rename from qa/rpc-tests/fundrawtransaction.py rename to test/functional/fundrawtransaction.py diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/test/functional/getblocktemplate_longpoll.py similarity index 100% rename from qa/rpc-tests/getblocktemplate_longpoll.py rename to test/functional/getblocktemplate_longpoll.py diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py similarity index 100% rename from qa/rpc-tests/getblocktemplate_proposals.py rename to test/functional/getblocktemplate_proposals.py diff --git a/qa/rpc-tests/getchaintips.py b/test/functional/getchaintips.py similarity index 100% rename from qa/rpc-tests/getchaintips.py rename to test/functional/getchaintips.py diff --git a/qa/rpc-tests/httpbasics.py b/test/functional/httpbasics.py similarity index 100% rename from qa/rpc-tests/httpbasics.py rename to test/functional/httpbasics.py diff --git a/qa/rpc-tests/import-rescan.py b/test/functional/import-rescan.py similarity index 100% rename from qa/rpc-tests/import-rescan.py rename to test/functional/import-rescan.py diff --git a/qa/rpc-tests/importmulti.py b/test/functional/importmulti.py similarity index 100% rename from qa/rpc-tests/importmulti.py rename to test/functional/importmulti.py diff --git a/qa/rpc-tests/importprunedfunds.py b/test/functional/importprunedfunds.py similarity index 100% rename from qa/rpc-tests/importprunedfunds.py rename to test/functional/importprunedfunds.py diff --git a/qa/rpc-tests/invalidateblock.py b/test/functional/invalidateblock.py similarity index 100% rename from qa/rpc-tests/invalidateblock.py rename to test/functional/invalidateblock.py diff --git a/qa/rpc-tests/invalidblockrequest.py b/test/functional/invalidblockrequest.py similarity index 100% rename from qa/rpc-tests/invalidblockrequest.py rename to test/functional/invalidblockrequest.py diff --git a/qa/rpc-tests/invalidtxrequest.py b/test/functional/invalidtxrequest.py similarity index 100% rename from qa/rpc-tests/invalidtxrequest.py rename to test/functional/invalidtxrequest.py diff --git a/qa/rpc-tests/keypool-hd.py b/test/functional/keypool-hd.py similarity index 100% rename from qa/rpc-tests/keypool-hd.py rename to test/functional/keypool-hd.py diff --git a/qa/rpc-tests/keypool.py b/test/functional/keypool.py similarity index 100% rename from qa/rpc-tests/keypool.py rename to test/functional/keypool.py diff --git a/qa/rpc-tests/listsinceblock.py b/test/functional/listsinceblock.py similarity index 100% rename from qa/rpc-tests/listsinceblock.py rename to test/functional/listsinceblock.py diff --git a/qa/rpc-tests/listtransactions.py b/test/functional/listtransactions.py similarity index 100% rename from qa/rpc-tests/listtransactions.py rename to test/functional/listtransactions.py diff --git a/qa/rpc-tests/llmq-chainlocks.py b/test/functional/llmq-chainlocks.py similarity index 100% rename from qa/rpc-tests/llmq-chainlocks.py rename to test/functional/llmq-chainlocks.py diff --git a/qa/rpc-tests/llmq-dkgerrors.py b/test/functional/llmq-dkgerrors.py similarity index 100% rename from qa/rpc-tests/llmq-dkgerrors.py rename to test/functional/llmq-dkgerrors.py diff --git a/qa/rpc-tests/llmq-is-cl-conflicts.py b/test/functional/llmq-is-cl-conflicts.py similarity index 100% rename from qa/rpc-tests/llmq-is-cl-conflicts.py rename to test/functional/llmq-is-cl-conflicts.py diff --git a/qa/rpc-tests/llmq-signing.py b/test/functional/llmq-signing.py similarity index 100% rename from qa/rpc-tests/llmq-signing.py rename to test/functional/llmq-signing.py diff --git a/qa/rpc-tests/llmq-simplepose.py b/test/functional/llmq-simplepose.py similarity index 100% rename from qa/rpc-tests/llmq-simplepose.py rename to test/functional/llmq-simplepose.py diff --git a/qa/rpc-tests/maxblocksinflight.py b/test/functional/maxblocksinflight.py similarity index 100% rename from qa/rpc-tests/maxblocksinflight.py rename to test/functional/maxblocksinflight.py diff --git a/qa/rpc-tests/maxuploadtarget.py b/test/functional/maxuploadtarget.py similarity index 100% rename from qa/rpc-tests/maxuploadtarget.py rename to test/functional/maxuploadtarget.py diff --git a/qa/rpc-tests/mempool_limit.py b/test/functional/mempool_limit.py similarity index 100% rename from qa/rpc-tests/mempool_limit.py rename to test/functional/mempool_limit.py diff --git a/qa/rpc-tests/mempool_packages.py b/test/functional/mempool_packages.py similarity index 100% rename from qa/rpc-tests/mempool_packages.py rename to test/functional/mempool_packages.py diff --git a/qa/rpc-tests/mempool_reorg.py b/test/functional/mempool_reorg.py similarity index 100% rename from qa/rpc-tests/mempool_reorg.py rename to test/functional/mempool_reorg.py diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/test/functional/mempool_resurrect_test.py similarity index 100% rename from qa/rpc-tests/mempool_resurrect_test.py rename to test/functional/mempool_resurrect_test.py diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/test/functional/mempool_spendcoinbase.py similarity index 100% rename from qa/rpc-tests/mempool_spendcoinbase.py rename to test/functional/mempool_spendcoinbase.py diff --git a/qa/rpc-tests/merkle_blocks.py b/test/functional/merkle_blocks.py similarity index 100% rename from qa/rpc-tests/merkle_blocks.py rename to test/functional/merkle_blocks.py diff --git a/qa/rpc-tests/multi_rpc.py b/test/functional/multi_rpc.py similarity index 100% rename from qa/rpc-tests/multi_rpc.py rename to test/functional/multi_rpc.py diff --git a/qa/rpc-tests/multikeysporks.py b/test/functional/multikeysporks.py similarity index 100% rename from qa/rpc-tests/multikeysporks.py rename to test/functional/multikeysporks.py diff --git a/qa/rpc-tests/nodehandling.py b/test/functional/nodehandling.py similarity index 100% rename from qa/rpc-tests/nodehandling.py rename to test/functional/nodehandling.py diff --git a/qa/rpc-tests/nulldummy.py b/test/functional/nulldummy.py similarity index 100% rename from qa/rpc-tests/nulldummy.py rename to test/functional/nulldummy.py diff --git a/qa/rpc-tests/p2p-acceptblock.py b/test/functional/p2p-acceptblock.py similarity index 100% rename from qa/rpc-tests/p2p-acceptblock.py rename to test/functional/p2p-acceptblock.py diff --git a/qa/rpc-tests/p2p-autoinstantsend.py b/test/functional/p2p-autoinstantsend.py similarity index 100% rename from qa/rpc-tests/p2p-autoinstantsend.py rename to test/functional/p2p-autoinstantsend.py diff --git a/qa/rpc-tests/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py similarity index 100% rename from qa/rpc-tests/p2p-compactblocks.py rename to test/functional/p2p-compactblocks.py diff --git a/qa/rpc-tests/p2p-fingerprint.py b/test/functional/p2p-fingerprint.py similarity index 100% rename from qa/rpc-tests/p2p-fingerprint.py rename to test/functional/p2p-fingerprint.py diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/test/functional/p2p-fullblocktest.py similarity index 100% rename from qa/rpc-tests/p2p-fullblocktest.py rename to test/functional/p2p-fullblocktest.py diff --git a/qa/rpc-tests/p2p-instantsend.py b/test/functional/p2p-instantsend.py similarity index 100% rename from qa/rpc-tests/p2p-instantsend.py rename to test/functional/p2p-instantsend.py diff --git a/qa/rpc-tests/p2p-leaktests.py b/test/functional/p2p-leaktests.py similarity index 100% rename from qa/rpc-tests/p2p-leaktests.py rename to test/functional/p2p-leaktests.py diff --git a/qa/rpc-tests/p2p-mempool.py b/test/functional/p2p-mempool.py similarity index 100% rename from qa/rpc-tests/p2p-mempool.py rename to test/functional/p2p-mempool.py diff --git a/qa/rpc-tests/p2p-timeouts.py b/test/functional/p2p-timeouts.py similarity index 100% rename from qa/rpc-tests/p2p-timeouts.py rename to test/functional/p2p-timeouts.py diff --git a/qa/rpc-tests/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py similarity index 100% rename from qa/rpc-tests/p2p-versionbits-warning.py rename to test/functional/p2p-versionbits-warning.py diff --git a/qa/rpc-tests/preciousblock.py b/test/functional/preciousblock.py similarity index 100% rename from qa/rpc-tests/preciousblock.py rename to test/functional/preciousblock.py diff --git a/qa/rpc-tests/prioritise_transaction.py b/test/functional/prioritise_transaction.py similarity index 100% rename from qa/rpc-tests/prioritise_transaction.py rename to test/functional/prioritise_transaction.py diff --git a/qa/rpc-tests/proxy_test.py b/test/functional/proxy_test.py similarity index 100% rename from qa/rpc-tests/proxy_test.py rename to test/functional/proxy_test.py diff --git a/qa/rpc-tests/pruning.py b/test/functional/pruning.py similarity index 100% rename from qa/rpc-tests/pruning.py rename to test/functional/pruning.py diff --git a/qa/rpc-tests/rawtransactions.py b/test/functional/rawtransactions.py similarity index 100% rename from qa/rpc-tests/rawtransactions.py rename to test/functional/rawtransactions.py diff --git a/qa/rpc-tests/receivedby.py b/test/functional/receivedby.py similarity index 100% rename from qa/rpc-tests/receivedby.py rename to test/functional/receivedby.py diff --git a/qa/rpc-tests/reindex.py b/test/functional/reindex.py similarity index 100% rename from qa/rpc-tests/reindex.py rename to test/functional/reindex.py diff --git a/qa/rpc-tests/rest.py b/test/functional/rest.py similarity index 100% rename from qa/rpc-tests/rest.py rename to test/functional/rest.py diff --git a/qa/rpc-tests/rpcbind_test.py b/test/functional/rpcbind_test.py similarity index 100% rename from qa/rpc-tests/rpcbind_test.py rename to test/functional/rpcbind_test.py diff --git a/qa/rpc-tests/rpcnamedargs.py b/test/functional/rpcnamedargs.py similarity index 100% rename from qa/rpc-tests/rpcnamedargs.py rename to test/functional/rpcnamedargs.py diff --git a/qa/rpc-tests/sendheaders.py b/test/functional/sendheaders.py similarity index 100% rename from qa/rpc-tests/sendheaders.py rename to test/functional/sendheaders.py diff --git a/qa/rpc-tests/signmessages.py b/test/functional/signmessages.py similarity index 100% rename from qa/rpc-tests/signmessages.py rename to test/functional/signmessages.py diff --git a/qa/rpc-tests/signrawtransactions.py b/test/functional/signrawtransactions.py similarity index 100% rename from qa/rpc-tests/signrawtransactions.py rename to test/functional/signrawtransactions.py diff --git a/qa/rpc-tests/smartfees.py b/test/functional/smartfees.py similarity index 100% rename from qa/rpc-tests/smartfees.py rename to test/functional/smartfees.py diff --git a/qa/rpc-tests/spentindex.py b/test/functional/spentindex.py similarity index 100% rename from qa/rpc-tests/spentindex.py rename to test/functional/spentindex.py diff --git a/qa/rpc-tests/sporks.py b/test/functional/sporks.py similarity index 100% rename from qa/rpc-tests/sporks.py rename to test/functional/sporks.py diff --git a/qa/rpc-tests/test_framework/__init__.py b/test/functional/test_framework/__init__.py similarity index 100% rename from qa/rpc-tests/test_framework/__init__.py rename to test/functional/test_framework/__init__.py diff --git a/qa/rpc-tests/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py similarity index 100% rename from qa/rpc-tests/test_framework/authproxy.py rename to test/functional/test_framework/authproxy.py diff --git a/qa/rpc-tests/test_framework/bignum.py b/test/functional/test_framework/bignum.py similarity index 100% rename from qa/rpc-tests/test_framework/bignum.py rename to test/functional/test_framework/bignum.py diff --git a/qa/rpc-tests/test_framework/blockstore.py b/test/functional/test_framework/blockstore.py similarity index 100% rename from qa/rpc-tests/test_framework/blockstore.py rename to test/functional/test_framework/blockstore.py diff --git a/qa/rpc-tests/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py similarity index 100% rename from qa/rpc-tests/test_framework/blocktools.py rename to test/functional/test_framework/blocktools.py diff --git a/qa/rpc-tests/test_framework/comptool.py b/test/functional/test_framework/comptool.py similarity index 100% rename from qa/rpc-tests/test_framework/comptool.py rename to test/functional/test_framework/comptool.py diff --git a/qa/rpc-tests/test_framework/coverage.py b/test/functional/test_framework/coverage.py similarity index 100% rename from qa/rpc-tests/test_framework/coverage.py rename to test/functional/test_framework/coverage.py diff --git a/qa/rpc-tests/test_framework/key.py b/test/functional/test_framework/key.py similarity index 100% rename from qa/rpc-tests/test_framework/key.py rename to test/functional/test_framework/key.py diff --git a/qa/rpc-tests/test_framework/mininode.py b/test/functional/test_framework/mininode.py similarity index 100% rename from qa/rpc-tests/test_framework/mininode.py rename to test/functional/test_framework/mininode.py diff --git a/qa/rpc-tests/test_framework/netutil.py b/test/functional/test_framework/netutil.py similarity index 100% rename from qa/rpc-tests/test_framework/netutil.py rename to test/functional/test_framework/netutil.py diff --git a/qa/rpc-tests/test_framework/script.py b/test/functional/test_framework/script.py similarity index 100% rename from qa/rpc-tests/test_framework/script.py rename to test/functional/test_framework/script.py diff --git a/qa/rpc-tests/test_framework/siphash.py b/test/functional/test_framework/siphash.py similarity index 100% rename from qa/rpc-tests/test_framework/siphash.py rename to test/functional/test_framework/siphash.py diff --git a/qa/rpc-tests/test_framework/socks5.py b/test/functional/test_framework/socks5.py similarity index 100% rename from qa/rpc-tests/test_framework/socks5.py rename to test/functional/test_framework/socks5.py diff --git a/qa/rpc-tests/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py similarity index 100% rename from qa/rpc-tests/test_framework/test_framework.py rename to test/functional/test_framework/test_framework.py diff --git a/qa/rpc-tests/test_framework/util.py b/test/functional/test_framework/util.py similarity index 100% rename from qa/rpc-tests/test_framework/util.py rename to test/functional/test_framework/util.py diff --git a/qa/pull-tester/rpc-tests.py b/test/functional/test_runner.py similarity index 92% rename from qa/pull-tester/rpc-tests.py rename to test/functional/test_runner.py index 1522df7ba4e6..0a1ee9cebf17 100755 --- a/qa/pull-tester/rpc-tests.py +++ b/test/functional/test_runner.py @@ -2,16 +2,15 @@ # Copyright (c) 2014-2016 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -""" -rpc-tests.py - run regression test suite +"""Run regression test suite. This module calls down into individual test cases via subprocess. It will forward all unrecognized arguments onto the individual test scripts. -RPC tests are disabled on Windows by default. Use --force to run them anyway. +Functional tests are disabled on Windows by default. Use --force to run them anyway. For a description of arguments recognized by test scripts, see -`qa/pull-tester/test_framework/test_framework.py:BitcoinTestFramework.main`. +`test/functional/test_framework/test_framework.py:BitcoinTestFramework.main`. """ @@ -102,7 +101,7 @@ ZMQ_SCRIPTS = [ # ZMQ test can only be run if Dash Core was built with zmq-enabled. - # call rpc_tests.py with -nozmq to explicitly exclude these tests. + # call test_runner.py with -nozmq to explicitly exclude these tests. "zmq_test.py"] EXTENDED_SCRIPTS = [ @@ -140,7 +139,7 @@ def main(): # Parse arguments and pass through unrecognised args parser = argparse.ArgumentParser(add_help=False, - usage='%(prog)s [rpc-test.py options] [script options] [scripts]', + usage='%(prog)s [test_runner.py options] [script options] [scripts]', description=__doc__, epilog=''' Help text and arguments for individual test script:''', @@ -160,7 +159,7 @@ def main(): # Read config generated by configure. config = configparser.ConfigParser() - config.read_file(open(os.path.dirname(__file__) + "/tests_config.ini")) + config.read_file(open(os.path.dirname(__file__) + "/config.ini")) enable_wallet = config["components"].getboolean("ENABLE_WALLET") enable_utils = config["components"].getboolean("ENABLE_UTILS") @@ -174,7 +173,7 @@ def main(): sys.exit(0) if not (enable_wallet and enable_utils and enable_bitcoind): - print("No rpc tests to run. Wallet, utils, and bitcoind must all be enabled") + print("No functional tests to run. Wallet, utils, and bitcoind must all be enabled") print("Rerun `configure` with -enable-wallet, -with-utils and -with-daemon and rerun make") sys.exit(0) @@ -184,7 +183,7 @@ def main(): import zmq except ImportError: print("ERROR: \"import zmq\" failed. Use -nozmq to run without the ZMQ tests." - "To run zmq tests, see dependency info in /qa/README.md.") + "To run zmq tests, see dependency info in /test/README.md.") raise # Build list of tests @@ -213,13 +212,13 @@ def main(): if not test_list: print("No valid test scripts specified. Check that your test is in one " - "of the test lists in rpc-tests.py, or run rpc-tests.py with no arguments to run all tests") + "of the test lists in test_runner.py, or run test_runner.py with no arguments to run all tests") sys.exit(0) if args.help: - # Print help for rpc-tests.py, then print help of the first script and exit. + # Print help for test_runner.py, then print help of the first script and exit. parser.print_help() - subprocess.check_call((config["environment"]["SRCDIR"] + '/qa/rpc-tests/' + test_list[0]).split() + ['-h']) + subprocess.check_call((config["environment"]["SRCDIR"] + '/test/functional/' + test_list[0]).split() + ['-h']) sys.exit(0) run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args) @@ -235,10 +234,10 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal if "BITCOIND" not in os.environ: os.environ["BITCOIND"] = build_dir + '/src/dashd' + exeext - tests_dir = src_dir + '/qa/rpc-tests/' + tests_dir = src_dir + '/test/functional/' flags = ["--srcdir={}/src".format(build_dir)] + args - flags.append("--cachedir=%s/qa/cache" % build_dir) + flags.append("--cachedir=%s/test/cache" % build_dir) if enable_coverage: coverage = RPCCoverage() @@ -256,7 +255,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal time_sum = 0 time0 = time.time() - job_queue = RPCTestHandler(jobs, tests_dir, test_list, flags) + job_queue = TestHandler(jobs, tests_dir, test_list, flags) max_len_name = len(max(test_list, key=len)) results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "PASSED", "DURATION") + BOLD[0] @@ -284,7 +283,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal sys.exit(not all_passed) -class RPCTestHandler: +class TestHandler: """ Trigger the testscrips passed in via the list. """ @@ -338,7 +337,7 @@ def get_next(self): class RPCCoverage(object): """ - Coverage reporting utilities for pull-tester. + Coverage reporting utilities for test_runner. Coverage calculation works by having each test script subprocess write coverage files into a particular directory. These files contain the RPC @@ -348,7 +347,7 @@ class RPCCoverage(object): After all tests complete, the commands run are combined and diff'd against the complete list to calculate uncovered RPC commands. - See also: qa/rpc-tests/test_framework/coverage.py + See also: test/functional/test_framework/coverage.py """ def __init__(self): @@ -376,7 +375,7 @@ def _get_uncovered_rpc_commands(self): Return a set of currently untested RPC commands. """ - # This is shared from `qa/rpc-tests/test-framework/coverage.py` + # This is shared from `test/functional/test-framework/coverage.py` reference_filename = 'rpc_interface.txt' coverage_file_prefix = 'coverage.' diff --git a/qa/rpc-tests/timestampindex.py b/test/functional/timestampindex.py similarity index 100% rename from qa/rpc-tests/timestampindex.py rename to test/functional/timestampindex.py diff --git a/qa/rpc-tests/txindex.py b/test/functional/txindex.py similarity index 100% rename from qa/rpc-tests/txindex.py rename to test/functional/txindex.py diff --git a/qa/rpc-tests/txn_clone.py b/test/functional/txn_clone.py similarity index 100% rename from qa/rpc-tests/txn_clone.py rename to test/functional/txn_clone.py diff --git a/qa/rpc-tests/txn_doublespend.py b/test/functional/txn_doublespend.py similarity index 100% rename from qa/rpc-tests/txn_doublespend.py rename to test/functional/txn_doublespend.py diff --git a/qa/rpc-tests/wallet-accounts.py b/test/functional/wallet-accounts.py similarity index 100% rename from qa/rpc-tests/wallet-accounts.py rename to test/functional/wallet-accounts.py diff --git a/qa/rpc-tests/wallet-dump.py b/test/functional/wallet-dump.py similarity index 100% rename from qa/rpc-tests/wallet-dump.py rename to test/functional/wallet-dump.py diff --git a/qa/rpc-tests/wallet-hd.py b/test/functional/wallet-hd.py similarity index 100% rename from qa/rpc-tests/wallet-hd.py rename to test/functional/wallet-hd.py diff --git a/qa/rpc-tests/wallet.py b/test/functional/wallet.py similarity index 100% rename from qa/rpc-tests/wallet.py rename to test/functional/wallet.py diff --git a/qa/rpc-tests/walletbackup.py b/test/functional/walletbackup.py similarity index 100% rename from qa/rpc-tests/walletbackup.py rename to test/functional/walletbackup.py diff --git a/qa/rpc-tests/zapwallettxes.py b/test/functional/zapwallettxes.py similarity index 100% rename from qa/rpc-tests/zapwallettxes.py rename to test/functional/zapwallettxes.py diff --git a/qa/rpc-tests/zmq_test.py b/test/functional/zmq_test.py similarity index 100% rename from qa/rpc-tests/zmq_test.py rename to test/functional/zmq_test.py diff --git a/src/test/bctest.py b/test/util/bctest.py similarity index 96% rename from src/test/bctest.py rename to test/util/bctest.py index c07ef6e3edac..b17cf77ae312 100644 --- a/src/test/bctest.py +++ b/test/util/bctest.py @@ -23,14 +23,14 @@ def parse_output(a, fmt): else: raise NotImplementedError("Don't know how to compare %s" % fmt) -def bctest(testDir, testObj, exeext): +def bctest(testDir, testObj, buildenv): """Runs a single test, comparing output and RC to expected output and RC. Raises an error if input can't be read, executable fails, or output/RC are not as expected. Error is caught by bctester() and reported. """ # Get the exec names and arguments - execprog = testObj['exec'] + exeext + execprog = buildenv.BUILDDIR + "/src/" + testObj['exec'] + buildenv.exeext execargs = testObj['args'] execrun = [execprog] + execargs @@ -124,7 +124,7 @@ def bctester(testDir, input_basename, buildenv): for testObj in input_data: try: - bctest(testDir, testObj, buildenv.exeext) + bctest(testDir, testObj, buildenv) logging.info("PASSED: " + testObj["description"]) except: logging.info("FAILED: " + testObj["description"]) diff --git a/test/util/bitcoin-util-test.py b/test/util/bitcoin-util-test.py new file mode 100755 index 000000000000..e09a25159d2c --- /dev/null +++ b/test/util/bitcoin-util-test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# Copyright 2014 BitPay Inc. +# Copyright 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +from __future__ import division,print_function,unicode_literals +import os +import sys +import argparse +import logging + +help_text="""Test framework for bitcoin utils. + +Runs automatically during `make check`. + +Can also be run manually.""" + +if __name__ == '__main__': + sys.path.append(os.path.dirname(os.path.abspath(__file__))) + import buildenv + import bctest + + parser = argparse.ArgumentParser(description=help_text) + parser.add_argument('-v', '--verbose', action='store_true') + args = parser.parse_args() + verbose = args.verbose + + if verbose: + level = logging.DEBUG + else: + level = logging.ERROR + formatter = '%(asctime)s - %(levelname)s - %(message)s' + # Add the format/level to the logger + logging.basicConfig(format = formatter, level=level) + + bctest.bctester(buildenv.SRCDIR + "/test/util/data", "bitcoin-util-test.json", buildenv) diff --git a/test/util/buildenv.py.in b/test/util/buildenv.py.in new file mode 100644 index 000000000000..33030b0348ab --- /dev/null +++ b/test/util/buildenv.py.in @@ -0,0 +1,4 @@ +#!/usr/bin/env python +exeext="@EXEEXT@" +SRCDIR="@abs_top_srcdir@" +BUILDDIR="@abs_top_builddir@" diff --git a/src/test/data/bitcoin-util-test.json b/test/util/data/bitcoin-util-test.json similarity index 100% rename from src/test/data/bitcoin-util-test.json rename to test/util/data/bitcoin-util-test.json diff --git a/src/test/data/blanktxv1.hex b/test/util/data/blanktxv1.hex similarity index 100% rename from src/test/data/blanktxv1.hex rename to test/util/data/blanktxv1.hex diff --git a/src/test/data/blanktxv1.json b/test/util/data/blanktxv1.json similarity index 100% rename from src/test/data/blanktxv1.json rename to test/util/data/blanktxv1.json diff --git a/src/test/data/blanktxv2.hex b/test/util/data/blanktxv2.hex similarity index 100% rename from src/test/data/blanktxv2.hex rename to test/util/data/blanktxv2.hex diff --git a/src/test/data/blanktxv2.json b/test/util/data/blanktxv2.json similarity index 100% rename from src/test/data/blanktxv2.json rename to test/util/data/blanktxv2.json diff --git a/src/test/data/tt-delin1-out.hex b/test/util/data/tt-delin1-out.hex similarity index 100% rename from src/test/data/tt-delin1-out.hex rename to test/util/data/tt-delin1-out.hex diff --git a/src/test/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json similarity index 100% rename from src/test/data/tt-delin1-out.json rename to test/util/data/tt-delin1-out.json diff --git a/src/test/data/tt-delout1-out.hex b/test/util/data/tt-delout1-out.hex similarity index 100% rename from src/test/data/tt-delout1-out.hex rename to test/util/data/tt-delout1-out.hex diff --git a/src/test/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json similarity index 100% rename from src/test/data/tt-delout1-out.json rename to test/util/data/tt-delout1-out.json diff --git a/src/test/data/tt-locktime317000-out.hex b/test/util/data/tt-locktime317000-out.hex similarity index 100% rename from src/test/data/tt-locktime317000-out.hex rename to test/util/data/tt-locktime317000-out.hex diff --git a/src/test/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json similarity index 100% rename from src/test/data/tt-locktime317000-out.json rename to test/util/data/tt-locktime317000-out.json diff --git a/src/test/data/tx394b54bb.hex b/test/util/data/tx394b54bb.hex similarity index 100% rename from src/test/data/tx394b54bb.hex rename to test/util/data/tx394b54bb.hex diff --git a/src/test/data/txcreate1.hex b/test/util/data/txcreate1.hex similarity index 100% rename from src/test/data/txcreate1.hex rename to test/util/data/txcreate1.hex diff --git a/src/test/data/txcreate1.json b/test/util/data/txcreate1.json similarity index 100% rename from src/test/data/txcreate1.json rename to test/util/data/txcreate1.json diff --git a/src/test/data/txcreate2.hex b/test/util/data/txcreate2.hex similarity index 100% rename from src/test/data/txcreate2.hex rename to test/util/data/txcreate2.hex diff --git a/src/test/data/txcreate2.json b/test/util/data/txcreate2.json similarity index 100% rename from src/test/data/txcreate2.json rename to test/util/data/txcreate2.json diff --git a/src/test/data/txcreatedata1.hex b/test/util/data/txcreatedata1.hex similarity index 100% rename from src/test/data/txcreatedata1.hex rename to test/util/data/txcreatedata1.hex diff --git a/src/test/data/txcreatedata1.json b/test/util/data/txcreatedata1.json similarity index 100% rename from src/test/data/txcreatedata1.json rename to test/util/data/txcreatedata1.json diff --git a/src/test/data/txcreatedata2.hex b/test/util/data/txcreatedata2.hex similarity index 100% rename from src/test/data/txcreatedata2.hex rename to test/util/data/txcreatedata2.hex diff --git a/src/test/data/txcreatedata2.json b/test/util/data/txcreatedata2.json similarity index 100% rename from src/test/data/txcreatedata2.json rename to test/util/data/txcreatedata2.json diff --git a/src/test/data/txcreatedata_seq0.hex b/test/util/data/txcreatedata_seq0.hex similarity index 100% rename from src/test/data/txcreatedata_seq0.hex rename to test/util/data/txcreatedata_seq0.hex diff --git a/src/test/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json similarity index 100% rename from src/test/data/txcreatedata_seq0.json rename to test/util/data/txcreatedata_seq0.json diff --git a/src/test/data/txcreatedata_seq1.hex b/test/util/data/txcreatedata_seq1.hex similarity index 100% rename from src/test/data/txcreatedata_seq1.hex rename to test/util/data/txcreatedata_seq1.hex diff --git a/src/test/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json similarity index 100% rename from src/test/data/txcreatedata_seq1.json rename to test/util/data/txcreatedata_seq1.json diff --git a/src/test/data/txcreatemultisig1.hex b/test/util/data/txcreatemultisig1.hex similarity index 100% rename from src/test/data/txcreatemultisig1.hex rename to test/util/data/txcreatemultisig1.hex diff --git a/src/test/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json similarity index 100% rename from src/test/data/txcreatemultisig1.json rename to test/util/data/txcreatemultisig1.json diff --git a/src/test/data/txcreatemultisig2.hex b/test/util/data/txcreatemultisig2.hex similarity index 100% rename from src/test/data/txcreatemultisig2.hex rename to test/util/data/txcreatemultisig2.hex diff --git a/src/test/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json similarity index 100% rename from src/test/data/txcreatemultisig2.json rename to test/util/data/txcreatemultisig2.json diff --git a/src/test/data/txcreateoutpubkey1.hex b/test/util/data/txcreateoutpubkey1.hex similarity index 100% rename from src/test/data/txcreateoutpubkey1.hex rename to test/util/data/txcreateoutpubkey1.hex diff --git a/src/test/data/txcreateoutpubkey1.json b/test/util/data/txcreateoutpubkey1.json similarity index 100% rename from src/test/data/txcreateoutpubkey1.json rename to test/util/data/txcreateoutpubkey1.json diff --git a/src/test/data/txcreatescript1.hex b/test/util/data/txcreatescript1.hex similarity index 100% rename from src/test/data/txcreatescript1.hex rename to test/util/data/txcreatescript1.hex diff --git a/src/test/data/txcreatescript1.json b/test/util/data/txcreatescript1.json similarity index 100% rename from src/test/data/txcreatescript1.json rename to test/util/data/txcreatescript1.json diff --git a/src/test/data/txcreatescript2.hex b/test/util/data/txcreatescript2.hex similarity index 100% rename from src/test/data/txcreatescript2.hex rename to test/util/data/txcreatescript2.hex diff --git a/src/test/data/txcreatescript2.json b/test/util/data/txcreatescript2.json similarity index 100% rename from src/test/data/txcreatescript2.json rename to test/util/data/txcreatescript2.json diff --git a/src/test/data/txcreatesignv1.hex b/test/util/data/txcreatesignv1.hex similarity index 100% rename from src/test/data/txcreatesignv1.hex rename to test/util/data/txcreatesignv1.hex diff --git a/src/test/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json similarity index 100% rename from src/test/data/txcreatesignv1.json rename to test/util/data/txcreatesignv1.json diff --git a/src/test/data/txcreatesignv2.hex b/test/util/data/txcreatesignv2.hex similarity index 100% rename from src/test/data/txcreatesignv2.hex rename to test/util/data/txcreatesignv2.hex From 16641e1b1afa3e116e7ece58d48fdd0c8863831e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 31 Mar 2017 12:57:22 +0200 Subject: [PATCH 023/987] Merge #10095: refactor: Move GetDifficulty out of `rpc/server.h` f885b67 refactor: Make rest.cpp dependency on `*toJSON` in `blockchain.cpp` explicit (Wladimir J. van der Laan) 8d8f28d refactor: Move RPCNotifyBlockChange out of `rpc/server.h` (Wladimir J. van der Laan) e6dcfee refactor: Move GetDifficulty out of `rpc/server.h` (Wladimir J. van der Laan) Tree-SHA512: fc2656611d18442f2fddba5ac1554d958151f6785c2039afdfc36735d7e71592d9686ff6cc7b2ad95180071d7514470e62c52d697c5a1e88f851bddaf5942edb --- src/Makefile.am | 1 + src/init.cpp | 1 + src/rest.cpp | 10 ++++------ src/rpc/blockchain.cpp | 13 ++++--------- src/rpc/blockchain.h | 40 ++++++++++++++++++++++++++++++++++++++++ src/rpc/mining.cpp | 1 + src/rpc/misc.cpp | 1 + src/rpc/server.h | 2 -- 8 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 src/rpc/blockchain.h diff --git a/src/Makefile.am b/src/Makefile.am index de6b93991ff2..060b9ddc98ea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -199,6 +199,7 @@ BITCOIN_CORE_H = \ protocol.h \ random.h \ reverselock.h \ + rpc/blockchain.h \ rpc/client.h \ rpc/protocol.h \ rpc/server.h \ diff --git a/src/init.cpp b/src/init.cpp index 65101215625f..71f1ce0e669b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -29,6 +29,7 @@ #include "policy/policy.h" #include "rpc/server.h" #include "rpc/register.h" +#include "rpc/blockchain.h" #include "script/standard.h" #include "script/sigcache.h" #include "scheduler.h" diff --git a/src/rest.cpp b/src/rest.cpp index c5a8c184a4a2..57c17257917e 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -9,6 +9,7 @@ #include "primitives/transaction.h" #include "validation.h" #include "httpserver.h" +#include "rpc/blockchain.h" #include "rpc/server.h" #include "streams.h" #include "sync.h" @@ -58,12 +59,9 @@ struct CCoin { } }; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); -extern UniValue mempoolInfoToJSON(); -extern UniValue mempoolToJSON(bool fVerbose = false); -extern void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -extern UniValue blockheaderToJSON(const CBlockIndex* blockindex); +/* Defined in rawtransaction.cpp */ +void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); +void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string message) { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index d08d518108fc..dad858c77966 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -4,6 +4,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "rpc/blockchain.h" + #include "amount.h" #include "chain.h" #include "chainparams.h" @@ -52,13 +54,6 @@ static CUpdatedBlock latestblock; extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -/** - * Get the difficulty of the net wrt to the given block index, or the chain tip if - * not provided. - * - * @return A floating point number that is a multiple of the main net minimum - * difficulty (4295032833 hashes). - */ double GetDifficulty(const CBlockIndex* blockindex) { if (blockindex == NULL) @@ -119,7 +114,7 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) return result; } -UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false) +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails) { UniValue result(UniValue::VOBJ); result.push_back(Pair("hash", blockindex->GetBlockHash().GetHex())); @@ -409,7 +404,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) info.push_back(Pair("instantlock", instantsend.IsLockedInstantSendTransaction(tx.GetHash()) || llmq::quorumInstantSendManager->IsLocked(tx.GetHash()))); } -UniValue mempoolToJSON(bool fVerbose = false) +UniValue mempoolToJSON(bool fVerbose) { if (fVerbose) { diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h new file mode 100644 index 000000000000..c021441b0a73 --- /dev/null +++ b/src/rpc/blockchain.h @@ -0,0 +1,40 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_RPC_BLOCKCHAIN_H +#define BITCOIN_RPC_BLOCKCHAIN_H + +class CBlock; +class CBlockIndex; +class CScript; +class CTransaction; +class uint256; +class UniValue; + +/** + * Get the difficulty of the net wrt to the given block index, or the chain tip if + * not provided. + * + * @return A floating point number that is a multiple of the main net minimum + * difficulty (4295032833 hashes). + */ +double GetDifficulty(const CBlockIndex* blockindex = nullptr); + +/** Callback for when block tip changed. */ +void RPCNotifyBlockChange(bool ibd, const CBlockIndex *); + +/** Block description to JSON */ +UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false); + +/** Mempool information to JSON */ +UniValue mempoolInfoToJSON(); + +/** Mempool to JSON */ +UniValue mempoolToJSON(bool fVerbose = false); + +/** Block header to JSON */ +UniValue blockheaderToJSON(const CBlockIndex* blockindex); + +#endif + diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 1d3ea083f35a..334db2987451 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -17,6 +17,7 @@ #include "miner.h" #include "net.h" #include "pow.h" +#include "rpc/blockchain.h" #include "rpc/server.h" #include "spork.h" #include "txmempool.h" diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 7810d4a6bb7d..fca5a477e37d 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -9,6 +9,7 @@ #include "init.h" #include "net.h" #include "netbase.h" +#include "rpc/blockchain.h" #include "rpc/server.h" #include "timedata.h" #include "txmempool.h" diff --git a/src/rpc/server.h b/src/rpc/server.h index 10d4a94f4d34..dde2419b242f 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -193,7 +193,6 @@ extern bool ParseBoolV(const UniValue& v, const std::string &strName); extern CAmount AmountFromValue(const UniValue& value); extern UniValue ValueFromAmount(const CAmount& amount); -extern double GetDifficulty(const CBlockIndex* blockindex = NULL); extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); @@ -201,6 +200,5 @@ bool StartRPC(); void InterruptRPC(); void StopRPC(); std::string JSONRPCExecBatch(const UniValue& vReq); -void RPCNotifyBlockChange(bool ibd, const CBlockIndex *); #endif // BITCOIN_RPCSERVER_H From b5968cd7a7eba4c5e015cbab3009a7e87d189d4d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 1 Apr 2017 12:25:50 +0200 Subject: [PATCH 024/987] Merge #10129: scheduler: fix sub-second precision with boost < 1.50 e025246 scheduler: fix sub-second precision with boost < 1.50 (Cory Fields) Tree-SHA512: b9d4875406c1a2bf3cb6412d7511c24d871bfba6a2ea5ccfbbf7392f2f8850027b001b776da422fea592878da21d897b1aa56d92bc2239869055dce79fd442ac --- src/scheduler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 07fcd0a88ee9..56d9e01ee1b4 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -23,7 +23,9 @@ CScheduler::~CScheduler() #if BOOST_VERSION < 105000 static boost::system_time toPosixTime(const boost::chrono::system_clock::time_point& t) { - return boost::posix_time::from_time_t(boost::chrono::system_clock::to_time_t(t)); + // Creating the posix_time using from_time_t loses sub-second precision. So rather than exporting the time_point to time_t, + // start with a posix_time at the epoch (0) and add the milliseconds that have passed since then. + return boost::posix_time::from_time_t(0) + boost::posix_time::milliseconds(boost::chrono::duration_cast(t.time_since_epoch()).count()); } #endif From 07ed44df6b16bf379f3ab0798ccff3ac295fe2f9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 2 Apr 2017 08:24:32 +0200 Subject: [PATCH 025/987] Merge #10136: build: Disable Wshadow warning 2c83911 build: Disable Wshadow warning (Wladimir J. van der Laan) Tree-SHA512: e3c1f7253c43449740760da287985b8027344dfc48c8a85ea9bca977c73cbaf75709d6e32ac0fea51eb89dccb48706a5abdf006be45375838df10ccba35e9aa1 --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index bacf8d3d21f8..2a820ec34561 100644 --- a/configure.ac +++ b/configure.ac @@ -271,7 +271,6 @@ if test "x$CXXFLAGS_overridden" = "xno"; then AX_CHECK_COMPILE_FLAG([-Wformat],[CXXFLAGS="$CXXFLAGS -Wformat"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wvla],[CXXFLAGS="$CXXFLAGS -Wvla"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wformat-security],[CXXFLAGS="$CXXFLAGS -Wformat-security"],,[[$CXXFLAG_WERROR]]) - AX_CHECK_COMPILE_FLAG([-Wshadow],[CXXFLAGS="$CXXFLAGS -Wshadow"],,[[$CXXFLAG_WERROR]]) ## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all ## unknown options if any other warning is produced. Test the -Wfoo case, and From 818ec218d6f7caf81af17dcacdd462eabc208171 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 2 Apr 2017 08:55:12 +0200 Subject: [PATCH 026/987] Merge #10128: Speed Up CuckooCache tests 3f098cc Decrease testcase sizes in cuckoocache tests (Jeremy Rubin) Tree-SHA512: 71a0e171be8d5473c791440aa4353d99b885b926b7284a3a1914c95e0c2c77925d5f3a6f329778cd81931a4e5832a082cb31d82ee8adb433d357d2e2b4f7a9e5 --- src/test/cuckoocache_tests.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 228b3e571ae2..a4e999dd572e 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -60,7 +60,8 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) { insecure_rand = FastRandomContext(true); CuckooCache::cache cc{}; - cc.setup_bytes(32 << 20); + size_t megabytes = 4; + cc.setup_bytes(megabytes << 20); uint256 v; for (int x = 0; x < 100000; ++x) { insecure_GetRandHash(v); @@ -135,7 +136,7 @@ BOOST_AUTO_TEST_CASE(cuckoocache_hit_rate_ok) * as a lower bound on performance. */ double HitRateThresh = 0.98; - size_t megabytes = 32; + size_t megabytes = 4; for (double load = 0.1; load < 2; load *= 2) { double hits = test_cache>(megabytes, load); BOOST_CHECK(normalize_hit_rate(hits, load) > HitRateThresh); @@ -204,7 +205,7 @@ void test_cache_erase(size_t megabytes) BOOST_AUTO_TEST_CASE(cuckoocache_erase_ok) { - size_t megabytes = 32; + size_t megabytes = 4; test_cache_erase>(megabytes); } @@ -291,7 +292,7 @@ void test_cache_erase_parallel(size_t megabytes) } BOOST_AUTO_TEST_CASE(cuckoocache_erase_parallel_ok) { - size_t megabytes = 32; + size_t megabytes = 4; test_cache_erase_parallel>(megabytes); } @@ -342,13 +343,13 @@ void test_cache_generations() } }; - const uint32_t BLOCK_SIZE = 10000; + const uint32_t BLOCK_SIZE = 1000; // We expect window size 60 to perform reasonably given that each epoch // stores 45% of the cache size (~472k). const uint32_t WINDOW_SIZE = 60; const uint32_t POP_AMOUNT = (BLOCK_SIZE / WINDOW_SIZE) / 2; const double load = 10; - const size_t megabytes = 32; + const size_t megabytes = 4; const size_t bytes = megabytes * (1 << 20); const uint32_t n_insert = static_cast(load * (bytes / sizeof(uint256))); From 9fa51cc6675b47292a888222e7eeaa1c1a1cd359 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 2 Apr 2017 12:51:58 +0200 Subject: [PATCH 027/987] Merge #10072: Remove sources of unreliablility in extended functional tests a4fd89f Make forknotify.py more robust (John Newbery) 1f3d78b Wait for connection to open in bip9-softforks.py (John Newbery) Tree-SHA512: de7d0002ee62ad97059b6f6c89b11f6e9901e3b4164ef6906bcd61e4ca499c277d9034784755966e5baf599869fad611b0b18f5547a384ceb5b7db3cc5bbd132 --- test/functional/bip9-softforks.py | 10 ++++------ test/functional/forknotify.py | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index e21a396f2e9e..1175b1b7bce1 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -200,16 +200,14 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance([[block, False]]) # Restart all - self.test.block_store.close() + self.test.clear_all_connections() stop_nodes(self.nodes) - shutil.rmtree(self.options.tmpdir) + shutil.rmtree(self.options.tmpdir + "/node0") self.setup_chain() self.setup_network() - self.test.block_store = BlockStore(self.options.tmpdir) - self.test.clear_all_connections() self.test.add_all_connections(self.nodes) - NetworkThread().start() # Start up network handling in another thread - + NetworkThread().start() + self.test.test_nodes[0].wait_for_verack() def get_tests(self): for test in itertools.chain( diff --git a/test/functional/forknotify.py b/test/functional/forknotify.py index c2724ba5df41..7a365438cc24 100755 --- a/test/functional/forknotify.py +++ b/test/functional/forknotify.py @@ -3,6 +3,8 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the -alertnotify option.""" +import os +import time from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * @@ -41,12 +43,19 @@ def run_test(self): self.nodes[1].generate(1) self.sync_all() + # Give bitcoind 10 seconds to write the alert notification + timeout = 10.0 + while timeout > 0: + if os.path.exists(self.alert_filename) and os.path.getsize(self.alert_filename): + break + time.sleep(0.1) + timeout -= 0.1 + else: + assert False, "-alertnotify did not warn of up-version blocks" + with open(self.alert_filename, 'r', encoding='utf8') as f: alert_text = f.read() - if len(alert_text) == 0: - raise AssertionError("-alertnotify did not warn of up-version blocks") - # Mine more up-version blocks, should not get more alerts: self.nodes[1].generate(1) self.sync_all() From 22b21f50cc77276d92583f65b6b99fc65868e0eb Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 2 Apr 2017 15:39:20 +0200 Subject: [PATCH 028/987] Merge #10077: [qa] Add setnetworkactive smoke test fa697b7 [qa] Add setnetworkactive smoke test (MarcoFalke) Tree-SHA512: 7205bae16f551e93383987392702e6853cfb06d4448735815fa116385cbf5deb6c4a8f521efdd43cf3cc59fede3b3d1ffe74e662890b74bcc21b5c13ce1f20b7 --- test/functional/net.py | 54 ++++++++++++++++++++++++++++++++++ test/functional/test_runner.py | 1 + 2 files changed, 55 insertions(+) create mode 100755 test/functional/net.py diff --git a/test/functional/net.py b/test/functional/net.py new file mode 100755 index 000000000000..e9463c7dc7df --- /dev/null +++ b/test/functional/net.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test RPC calls related to net. + +Tests correspond to code in rpc/net.cpp. +""" + +from decimal import Decimal +import time + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.authproxy import JSONRPCException +from test_framework.util import ( + assert_equal, + start_nodes, + connect_nodes_bi, +) + + +class NetTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 2 + + def setup_network(self): + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + connect_nodes_bi(self.nodes, 0, 1) + self.is_network_split = False + self.sync_all() + + def run_test(self): + assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) + assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) # bilateral connection + + self.nodes[0].setnetworkactive(False) + assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False) + timeout = 3 + while self.nodes[0].getnetworkinfo()['connections'] != 0: + # Wait a bit for all sockets to close + assert timeout > 0, 'not all connections closed in time' + timeout -= 0.1 + time.sleep(0.1) + + self.nodes[0].setnetworkactive(True) + connect_nodes_bi(self.nodes, 0, 1) + assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) + assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) + + +if __name__ == '__main__': + NetTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 0a1ee9cebf17..cc9d0134c57d 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -79,6 +79,7 @@ 'decodescript.py', 'blockchain.py', 'disablewallet.py', + 'net.py', 'keypool.py', 'keypool-hd.py', 'p2p-mempool.py', From 198808894959f8071924d2ff40c9f1b418a708d6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 3 Apr 2017 12:05:43 +0200 Subject: [PATCH 029/987] Merge #10058: No need to use OpenSSL malloc/free 6d5dd60 No need to use OpenSSL malloc/free (Thomas Snider) Tree-SHA512: 29f790067ffd5a10a8e1a621318a0ba445691f57c804aa3b7c8ca372c8408d8c7fe703c42b48018e400fc32e3feff5ab401d97433910ce2c50e69da0b8a6662e --- src/util.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 82bcf74e4d09..580bf7248b3c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -141,26 +141,24 @@ std::atomic fReopenDebugLog(false); CTranslationInterface translationInterface; /** Init OpenSSL library multithreading support */ -static CCriticalSection** ppmutexOpenSSL; +static std::unique_ptr ppmutexOpenSSL; void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS { if (mode & CRYPTO_LOCK) { - ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]); + ENTER_CRITICAL_SECTION(ppmutexOpenSSL[i]); } else { - LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]); + LEAVE_CRITICAL_SECTION(ppmutexOpenSSL[i]); } } -// Init +// Singleton for wrapping OpenSSL setup/teardown. class CInit { public: CInit() { // Init OpenSSL library multithreading support - ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*)); - for (int i = 0; i < CRYPTO_num_locks(); i++) - ppmutexOpenSSL[i] = new CCriticalSection(); + ppmutexOpenSSL.reset(new CCriticalSection[CRYPTO_num_locks()]); CRYPTO_set_locking_callback(locking_callback); // OpenSSL can optionally load a config file which lists optional loadable modules and engines. @@ -184,9 +182,8 @@ class CInit RAND_cleanup(); // Shutdown OpenSSL library multithreading support CRYPTO_set_locking_callback(NULL); - for (int i = 0; i < CRYPTO_num_locks(); i++) - delete ppmutexOpenSSL[i]; - OPENSSL_free(ppmutexOpenSSL); + // Clear the set of locks now to maintain symmetry with the constructor. + ppmutexOpenSSL.reset(); } } instance_of_cinit; From f471b75aec9a6cf91e4a503fe015938293737b93 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 3 Apr 2017 13:24:09 +0200 Subject: [PATCH 030/987] Merge #9533: Allow non-power-of-2 signature cache sizes 7482781 Allow non-power-of-2 signature cache sizes (Pieter Wuille) Tree-SHA512: 5731c22b46c5ae81cf6d52000c28e39b243a47d96d91079942a5b5a10db214449217f71aa2195e18f8a3917cb206b04c75dc13e4522eb700a1dbf1819013ba22 --- src/cuckoocache.h | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/cuckoocache.h b/src/cuckoocache.h index ff47e9776b64..58375494555e 100644 --- a/src/cuckoocache.h +++ b/src/cuckoocache.h @@ -154,7 +154,7 @@ class bit_packed_atomic_flags * @tparam Element should be a movable and copyable type * @tparam Hash should be a function/callable which takes a template parameter * hash_select and an Element and extracts a hash from it. Should return - * high-entropy hashes for `Hash h; h<0>(e) ... h<7>(e)`. + * high-entropy uint32_t hashes for `Hash h; h<0>(e) ... h<7>(e)`. */ template class cache @@ -193,12 +193,6 @@ class cache */ uint32_t epoch_size; - /** hash_mask should be set to appropriately mask out a hash such that every - * masked hash is [0,size), eg, if floor(log2(size)) == 20, then hash_mask - * should be (1<<20)-1 - */ - uint32_t hash_mask; - /** depth_limit determines how many elements insert should try to replace. * Should be set to log2(n)*/ uint8_t depth_limit; @@ -217,14 +211,14 @@ class cache */ inline std::array compute_hashes(const Element& e) const { - return {{hash_function.template operator()<0>(e) & hash_mask, - hash_function.template operator()<1>(e) & hash_mask, - hash_function.template operator()<2>(e) & hash_mask, - hash_function.template operator()<3>(e) & hash_mask, - hash_function.template operator()<4>(e) & hash_mask, - hash_function.template operator()<5>(e) & hash_mask, - hash_function.template operator()<6>(e) & hash_mask, - hash_function.template operator()<7>(e) & hash_mask}}; + return {{(uint32_t)((hash_function.template operator()<0>(e) * (uint64_t)size) >> 32), + (uint32_t)((hash_function.template operator()<1>(e) * (uint64_t)size) >> 32), + (uint32_t)((hash_function.template operator()<2>(e) * (uint64_t)size) >> 32), + (uint32_t)((hash_function.template operator()<3>(e) * (uint64_t)size) >> 32), + (uint32_t)((hash_function.template operator()<4>(e) * (uint64_t)size) >> 32), + (uint32_t)((hash_function.template operator()<5>(e) * (uint64_t)size) >> 32), + (uint32_t)((hash_function.template operator()<6>(e) * (uint64_t)size) >> 32), + (uint32_t)((hash_function.template operator()<7>(e) * (uint64_t)size) >> 32)}}; } /* end @@ -305,7 +299,7 @@ class cache } /** setup initializes the container to store no more than new_size - * elements. setup rounds down to a power of two size. + * elements. * * setup should only be called once. * @@ -316,8 +310,7 @@ class cache { // depth_limit must be at least one otherwise errors can occur. depth_limit = static_cast(std::log2(static_cast(std::max((uint32_t)2, new_size)))); - size = 1 << depth_limit; - hash_mask = size-1; + size = std::max(2, new_size); table.resize(size); collection_flags.setup(size); epoch_flags.resize(size); From 13cdff4989f707efef451c32eb3907dea9acd65d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 5 Apr 2017 07:57:17 +0200 Subject: [PATCH 031/987] Merge #10104: linearize script: Option to use RPC cookie bd41d98 Datadir option in linearize scripts (Andrew Chow) Tree-SHA512: 0d11866b574986c087ec962a8a9fc0b6dfee8175ae20ef827f8b4a143f657c5bffc9f9696e9dabf29b68002003a5b6a7d8ac473231b5c9c81c3a4fa0318f5bd0 --- contrib/linearize/README.md | 3 ++- contrib/linearize/example-linearize.cfg | 1 + contrib/linearize/linearize-hashes.py | 23 ++++++++++++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/contrib/linearize/README.md b/contrib/linearize/README.md index b83de046fe89..dd220b98d377 100644 --- a/contrib/linearize/README.md +++ b/contrib/linearize/README.md @@ -11,7 +11,8 @@ https://github.com/dashpay/dash_hash $ ./linearize-hashes.py linearize.cfg > hashlist.txt Required configuration file settings for linearize-hashes: -* RPC: `rpcuser`, `rpcpassword` +* RPC: `datadir` (Required if `rpcuser` and `rpcpassword` are not specified) +* RPC: `rpcuser`, `rpcpassword` (Required if `datadir` is not specified) Optional config file setting for linearize-hashes: * RPC: `host` (Default: `127.0.0.1`) diff --git a/contrib/linearize/example-linearize.cfg b/contrib/linearize/example-linearize.cfg index f1376bf34de3..3fea810ea68b 100644 --- a/contrib/linearize/example-linearize.cfg +++ b/contrib/linearize/example-linearize.cfg @@ -1,6 +1,7 @@ # bitcoind RPC settings (linearize-hashes) rpcuser=someuser rpcpassword=somepassword +#datadir=~/.bitcoin host=127.0.0.1 port=9998 diff --git a/contrib/linearize/linearize-hashes.py b/contrib/linearize/linearize-hashes.py index ebd9f1e75a0b..1a2f537443b6 100755 --- a/contrib/linearize/linearize-hashes.py +++ b/contrib/linearize/linearize-hashes.py @@ -16,6 +16,8 @@ import re import base64 import sys +import os +import os.path settings = {} @@ -93,6 +95,14 @@ def get_block_hashes(settings, max_blocks_per_call=10000): height += num_blocks +def get_rpc_cookie(): + # Open the cookie file + with open(os.path.join(os.path.expanduser(settings['datadir']), '.cookie'), 'r') as f: + combined = f.readline() + combined_split = combined.split(":") + settings['rpcuser'] = combined_split[0] + settings['rpcpassword'] = combined_split[1] + if __name__ == '__main__': if len(sys.argv) != 2: print("Usage: linearize-hashes.py CONFIG-FILE") @@ -122,8 +132,15 @@ def get_block_hashes(settings, max_blocks_per_call=10000): settings['max_height'] = 313000 if 'rev_hash_bytes' not in settings: settings['rev_hash_bytes'] = 'false' + + use_userpass = True + use_datadir = False if 'rpcuser' not in settings or 'rpcpassword' not in settings: - print("Missing username and/or password in cfg file", file=stderr) + use_userpass = False + if 'datadir' in settings and not use_userpass: + use_datadir = True + if not use_userpass and not use_datadir: + print("Missing datadir or username and/or password in cfg file", file=stderr) sys.exit(1) settings['port'] = int(settings['port']) @@ -133,4 +150,8 @@ def get_block_hashes(settings, max_blocks_per_call=10000): # Force hash byte format setting to be lowercase to make comparisons easier. settings['rev_hash_bytes'] = settings['rev_hash_bytes'].lower() + # Get the rpc user and pass from the cookie if the datadir is set + if use_datadir: + get_rpc_cookie() + get_block_hashes(settings) From 3dcaf47494ca8c84cd0bd17ad59808446fa19dbd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 10 Apr 2017 09:47:23 +0200 Subject: [PATCH 032/987] Merge #10166: Ignore Doxyfile generated from Doxyfile.in template. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 9eaf718 Ignore Doxyfile generated from Doxyfile.in template. (Pavel Janík) Tree-SHA512: 03d6d0fb4a708d9e41ada8b6d3d277f8c66abc2f07081629ac81ed90a3e5b2d76fa2faab9afb2ee8c91597ee031b3f5c6923d5658019321e290cdf6a70724896 --- doc/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/.gitignore diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 000000000000..38498103bb17 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +Doxyfile From e5ecff6e8af3b3eb85c56b04904aea635f4e55fa Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 10 Apr 2017 14:19:48 +0200 Subject: [PATCH 033/987] Merge #9949: [bench] Avoid function call arguments which are pointers to uninitialized values 218d915 [bench] Avoid function call arguments which are pointers to uninitialized values (practicalswift) Tree-SHA512: 68d62e9442094f171433291b7f13dba20fc7ead5fd7f2292e1eb97ae51aa2345d40224c4a65c2e5d3552802b3cd0f675a82b6181cf5b77e964355650b25089f0 --- src/bench/checkblock.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp index 018d4f508e4a..45ac54d62a34 100644 --- a/src/bench/checkblock.cpp +++ b/src/bench/checkblock.cpp @@ -20,7 +20,7 @@ static void DeserializeBlockTest(benchmark::State& state) CDataStream stream((const char*)raw_bench::block813851, (const char*)&raw_bench::block813851[sizeof(raw_bench::block813851)], SER_NETWORK, PROTOCOL_VERSION); - char a; + char a = '\0'; stream.write(&a, 1); // Prevent compaction while (state.KeepRunning()) { @@ -35,7 +35,7 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state) CDataStream stream((const char*)raw_bench::block813851, (const char*)&raw_bench::block813851[sizeof(raw_bench::block813851)], SER_NETWORK, PROTOCOL_VERSION); - char a; + char a = '\0'; stream.write(&a, 1); // Prevent compaction Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus(); From 23530a88a8802b438dc0a40e253aeae79bb42e4d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 10 Apr 2017 14:44:16 +0200 Subject: [PATCH 034/987] Merge #10135: [p2p] Send the correct error code in reject messages 5d08c9c Send the correct error code in reject messages (John Newbery) Tree-SHA512: 0cd3ef3ae202584b138cc0bbfba4125635822e0c5a755fb9276a604b39286959ab22dabc3104aa5d7e71358cd69d965de2a333ff04bf3e8ed43cf0296ac01264 --- src/net_processing.cpp | 6 +++--- src/validation.cpp | 10 ++++++---- test/functional/p2p-fullblocktest.py | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 1df626b70fd0..6a32b8455ee5 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -917,8 +917,8 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta int nDoS = 0; if (state.IsInvalid(nDoS)) { - if (it != mapBlockSource.end() && State(it->second.first)) { - assert (state.GetRejectCode() < REJECT_INTERNAL); // Blocks are never rejected with internal reject codes + // Don't send reject message with code 0 or an internal reject code. + if (it != mapBlockSource.end() && State(it->second.first) && state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) { CBlockReject reject = {(unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), hash}; State(it->second.first)->rejects.push_back(reject); if (nDoS > 0 && it->second.second) @@ -2348,7 +2348,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LogPrint("mempoolrej", "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state)); - if (state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P + if (state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(), state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash)); if (nDoS > 0) { diff --git a/src/validation.cpp b/src/validation.cpp index f4095e2ec4e3..de9fe3bb5786 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2185,7 +2185,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), 0.001 * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * 0.000001); if (!control.Wait()) - return state.DoS(100, false); + return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed"); int64_t nTime4 = GetTimeMicros(); nTimeVerify += nTime4 - nTime2; LogPrint("bench", " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime4 - nTime2), nInputs <= 1 ? 0 : 0.001 * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * 0.000001); @@ -3338,10 +3338,12 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati return true; int nHeight = pindexPrev->nHeight+1; - // Don't accept any forks from the main chain prior to last checkpoint + // Don't accept any forks from the main chain prior to last checkpoint. + // GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our + // MapBlockIndex. CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(chainparams.Checkpoints()); if (pcheckpoint && nHeight < pcheckpoint->nHeight) - return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight)); + return state.DoS(100, error("%s: forked chain older than last checkpoint (height %d)", __func__, nHeight), REJECT_CHECKPOINT, "bad-fork-prior-to-checkpoint"); return true; } @@ -3471,7 +3473,7 @@ static bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state CBlockIndex* pindexPrev = NULL; BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock); if (mi == mapBlockIndex.end()) - return state.DoS(10, error("%s: prev block not found", __func__), 0, "bad-prevblk"); + return state.DoS(10, error("%s: prev block not found", __func__), 0, "prev-blk-not-found"); pindexPrev = (*mi).second; assert(pindexPrev); diff --git a/test/functional/p2p-fullblocktest.py b/test/functional/p2p-fullblocktest.py index 90ec10758ec5..f0602168601f 100755 --- a/test/functional/p2p-fullblocktest.py +++ b/test/functional/p2p-fullblocktest.py @@ -404,7 +404,7 @@ def update_block(block_number, new_transactions): # Extend the b26 chain to make sure bitcoind isn't accepting b26 b27 = block(27, spend=out[7]) - yield rejected(RejectResult(0, b'bad-prevblk')) + yield rejected(False) # Now try a too-large-coinbase script tip(15) @@ -416,7 +416,7 @@ def update_block(block_number, new_transactions): # Extend the b28 chain to make sure bitcoind isn't accepting b28 b29 = block(29, spend=out[7]) - yield rejected(RejectResult(0, b'bad-prevblk')) + yield rejected(False) # b30 has a max-sized coinbase scriptSig. tip(23) From dccd6970bf042aa75e3ee54a694a3d3cb942aba2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 10 Apr 2017 15:16:34 +0200 Subject: [PATCH 035/987] Merge #10164: Wallet: reduce excess logic InMempool() 3491476 Wallet: reduce excess logic InMemPool() (Kewde) Tree-SHA512: 554ea2827cfd482281fae0ba3d0a7989dbfeace98a35462732ea08bf3cc94c9564a9ea8ca2fa9905b963367d0b56a490ef0d83ceb6731c8f06187de98b6a7f23 --- src/wallet/wallet.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f7892af93733..0077c398da27 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2186,10 +2186,7 @@ CAmount CWalletTx::GetChange() const bool CWalletTx::InMempool() const { LOCK(mempool.cs); - if (mempool.exists(GetHash())) { - return true; - } - return false; + return mempool.exists(GetHash()); } bool CWalletTx::IsTrusted() const From 0db1328a246445a90e995ac5ff1a8ed4576d265f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 12 Apr 2017 20:15:06 +0200 Subject: [PATCH 036/987] Merge #10177: Changed "Send" button default status from true to false 8c3e6c6 Changed "Send" button default status from true to false (KibbledJiveElkZoo) Tree-SHA512: e60d7481351e88925d99b33bdb616f3c234e93ef052571b9c4a1328186ec9abb8b61b0c4299afcb731edad2634aef6b1adaad121646b6c0c56dc933662904674 --- src/qt/forms/sendcoinsdialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 97f2f036d496..4a210ceacde5 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -1221,7 +1221,7 @@ false - true + false From 632956a8066fa80d6dec15c9d169a03e1096f18a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 17 Apr 2017 04:46:34 -0700 Subject: [PATCH 037/987] Merge #9693: Prevent integer overflow in ReadVarInt. 45f0961 Prevent integer overflow in ReadVarInt. (Gregory Maxwell) Tree-SHA512: 385ea0efb6b59d44c45a49227e5f6fff236b4775544cbeb236312a3fd87fd75c226ac56f7aa1bca66b853639da75a579610074f7582f92cf2ebd4a74bc40f6f0 --- src/serialize.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index 55e1e67d54c8..99801f7e50dd 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -352,11 +352,18 @@ I ReadVarInt(Stream& is) I n = 0; while(true) { unsigned char chData = ser_readdata8(is); + if (n > (std::numeric_limits::max() >> 7)) { + throw std::ios_base::failure("ReadVarInt(): size too large"); + } n = (n << 7) | (chData & 0x7F); - if (chData & 0x80) + if (chData & 0x80) { + if (n == std::numeric_limits::max()) { + throw std::ios_base::failure("ReadVarInt(): size too large"); + } n++; - else + } else { return n; + } } } From 383d1819a9a7d912906b51ce9d93e1e5c91260f4 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 18 Apr 2017 08:24:57 +0200 Subject: [PATCH 038/987] Merge #10211: [doc] Contributor fixes & new "finding reviewers" section 3ddd227 [doc] Add blob about finding reviewers. (Kalle Alm) 846dc17 [doc] Wording fixes in CONTRIBUTING.md. (Kalle Alm) Tree-SHA512: 232e6496769f0fba1022da2e9a3add10dcec721e6cc168d552445125849a8c02729a71b7c526bbff30c7428bcdcfdd92b424014fbb6310148392d261408b4044 --- CONTRIBUTING.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 078e0ec756b1..c9b77c54cc8c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,8 +37,8 @@ fixes or code moves with actual code changes. Commit messages should be verbose by default consisting of a short subject line (50 chars max), a blank line and detailed explanatory text as separate -paragraph(s); unless the title alone is self-explanatory (like "Corrected typo -in init.cpp") then a single title line is sufficient. Commit messages should be +paragraph(s), unless the title alone is self-explanatory (like "Corrected typo +in init.cpp") in which case a single title line is sufficient. Commit messages should be helpful to people reading your code in the future, so explain the reasoning for your decisions. Further explanation [here](http://chris.beams.io/posts/git-commit/). @@ -225,6 +225,37 @@ discussed extensively on the mailing list and IRC, be accompanied by a widely discussed BIP and have a generally widely perceived technical consensus of being a worthwhile change based on the judgement of the maintainers. +### Finding Reviewers + +As most reviewers are themselves developers with their own projects, the review +process can be quite lengthy, and some amount of patience is required. If you find +that you've been waiting for a pull request to be given attention for several +months, there may be a number of reasons for this, some of which you can do something +about: + + - It may be because of a feature freeze due to an upcoming release. During this time, + only bug fixes are taken into consideration. If your pull request is a new feature, + it will not be prioritized until the release is over. Wait for release. + - It may be because the changes you are suggesting do not appeal to people. Rather than + nits and critique, which require effort and means they care enough to spend time on your + contribution, thundering silence is a good sign of widespread (mild) dislike of a given change + (because people don't assume *others* won't actually like the proposal). Don't take + that personally, though! Instead, take another critical look at what you are suggesting + and see if it: changes too much, is too broad, doesn't adhere to the + [developer notes](doc/developer-notes.md), is dangerous or insecure, is messily written, etc. + Identify and address any of the issues you find. Then ask e.g. on IRC if someone could give + their opinion on the concept itself. + - It may be because your code is too complex for all but a few people. And those people + may not have realized your pull request even exists. A great way to find people who + are qualified and care about the code you are touching is the + [Git Blame feature](https://help.github.com/articles/tracing-changes-in-a-file/). Simply + find the person touching the code you are touching before you and see if you can find + them and give them a nudge. Don't be incessant about the nudging though. + - Finally, if all else fails, ask on IRC or elsewhere for someone to give your pull request + a look. If you think you've been waiting an unreasonably long amount of time (month+) for + no particular reason (few lines changed, etc), this is totally fine. Try to return the favor + when someone else is asking for feedback on their code, and universe balances out. + Release Policy -------------- From a089c9325ebe0d896e6e8e3c305c176b8e32fa09 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 19 Apr 2017 12:29:51 +0200 Subject: [PATCH 039/987] Merge #9827: Improve ScanForWalletTransactions return value 30abce7 Improve ScanForWalletTransactions return value (Russell Yanofsky) Tree-SHA512: 195028553b103052a842b6a37e67410118a20c32475b80f7fd22d6d8622f92eca1c2d84f291d1092bef2161d3187d91052799b533e1e265b7613d51955490b8d --- src/wallet/test/wallet_tests.cpp | 11 +++++++++++ src/wallet/wallet.cpp | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 3313a54549b3..c23614eef740 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -426,6 +426,17 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Failed to rescan before time %d, transactions may be missing.\"}},{\"success\":true}]", newTip->GetBlockTimeMax())); ::pwalletMain = backup; } + + // Verify ScanForWalletTransactions does not return null when the scan is + // elided due to the nTimeFirstKey optimization. + { + CWallet wallet; + { + LOCK(wallet.cs_wallet); + wallet.UpdateTimeFirstKey(newTip->GetBlockTime() + 7200 + 1); + } + BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(newTip)); + } } // Verify importwallet RPC starts rescan at earliest block with timestamp diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0077c398da27..072250247976 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1822,16 +1822,17 @@ void CWalletTx::GetAccountAmounts(const std::string& strAccount, CAmount& nRecei * exist in the wallet will be updated. * * Returns pointer to the first block in the last contiguous range that was - * successfully scanned. - * + * successfully scanned or elided (elided if pIndexStart points at a block + * before CWallet::nTimeFirstKey). Returns null if there is no such range, or + * the range doesn't include chainActive.Tip(). */ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) { - CBlockIndex* ret = nullptr; int64_t nNow = GetTime(); const CChainParams& chainParams = Params(); CBlockIndex* pindex = pindexStart; + CBlockIndex* ret = pindexStart; { LOCK2(cs_main, cs_wallet); From a3467dd26986a73edbf0972b67ef1b401e377c4b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 21 Apr 2017 10:59:01 +0200 Subject: [PATCH 040/987] Merge #10228: build: regenerate bitcoin-config.h as necessary 91ab8f5 build: fix bitcoin-config.h regeneration after touching build files (Cory Fields) 3577603 build: remove wonky auto top-level convenience targets (Cory Fields) Tree-SHA512: 2e68634439eeb7eca43cd2858135a583bfe0cf146e021a8384a24f7267aacc6f99bdc7a6d497a04d32e6a03e9446f0f599afb5bd53346dadf19f47d5fb2ea9f9 --- src/Makefile.am | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 060b9ddc98ea..054122111776 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -638,6 +638,14 @@ config/stamp-h1: $(top_srcdir)/$(subdir)/config/dash-config.h.in $(top_builddir) $(top_srcdir)/$(subdir)/config/dash-config.h.in: $(am__configure_deps) $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/dash-config.h.in + +config/bitcoin-config.h: config/stamp-h1 + @$(MAKE) -C $(top_builddir) $(subdir)/$(@) +config/stamp-h1: $(top_srcdir)/$(subdir)/config/bitcoin-config.h.in $(top_builddir)/config.status + $(AM_V_at)$(MAKE) -C $(top_builddir) $(subdir)/$(@) +$(top_srcdir)/$(subdir)/config/bitcoin-config.h.in: $(am__configure_deps) + $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/bitcoin-config.h.in + clean-local: -$(MAKE) -C secp256k1 clean -$(MAKE) -C univalue clean From 317b797e2af6bb96b805c7fb89d7c40e4c6e8dac Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 26 Apr 2017 11:43:52 +0200 Subject: [PATCH 041/987] Merge #9670: contrib: github-merge improvements b508424 contrib: github-merge improvements (Wladimir J. van der Laan) Tree-SHA512: 56a34e887716bf6bfcd1b6520f6b9a1bb742e1ad17e75618caf982af71fceb75d50caec1bf4279cb9a2f7a74319f1bcec4c824682841bd6e994acc0991616451 --- contrib/devtools/github-merge.py | 55 +++++++++++++++----------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py index 3fee39143dad..03ccf5b62411 100755 --- a/contrib/devtools/github-merge.py +++ b/contrib/devtools/github-merge.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2016 The Bitcoin Core developers +# Copyright (c) 2016-2017 Bitcoin Core Developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -15,7 +15,7 @@ # In case of a clean merge that is accepted by the user, the local branch with # name $BRANCH is overwritten with the merged result, and optionally pushed. from __future__ import division,print_function,unicode_literals -import os +import os,sys from sys import stdin,stdout,stderr import argparse import hashlib @@ -127,6 +127,9 @@ def tree_sha512sum(commit='HEAD'): raise IOError('Non-zero return value executing git cat-file') return overall.hexdigest() +def print_merge_details(pull, title, branch, base_branch, head_branch): + print('%s#%s%s %s %sinto %s%s' % (ATTR_RESET+ATTR_PR,pull,ATTR_RESET,title,ATTR_RESET+ATTR_PR,branch,ATTR_RESET)) + subprocess.check_call([GIT,'log','--graph','--topo-order','--pretty=format:'+COMMIT_FORMAT,base_branch+'..'+head_branch]) def parse_arguments(): epilog = ''' @@ -171,7 +174,7 @@ def main(): info = retrieve_pr_info(repo,pull) if info is None: exit(1) - title = info['title'] + title = info['title'].strip() # precedence order for destination branch argument: # - command line argument # - githubmerge.branch setting @@ -256,8 +259,7 @@ def main(): printf("ERROR: Cannot update message.",file=stderr) exit(4) - print('%s#%s%s %s %sinto %s%s' % (ATTR_RESET+ATTR_PR,pull,ATTR_RESET,title,ATTR_RESET+ATTR_PR,branch,ATTR_RESET)) - subprocess.check_call([GIT,'log','--graph','--topo-order','--pretty=format:'+COMMIT_FORMAT,base_branch+'..'+head_branch]) + print_merge_details(pull, title, branch, base_branch, head_branch) print() # Run test command if configured. @@ -276,12 +278,6 @@ def main(): print("Difference with github ignored.",file=stderr) else: exit(6) - reply = ask_prompt("Press 'd' to accept the diff.") - if reply.lower() == 'd': - print("Diff accepted.",file=stderr) - else: - print("ERROR: Diff rejected.",file=stderr) - exit(6) else: # Verify the result manually. print("Dropping you on a shell so you can try building/testing the merged source.",file=stderr) @@ -290,12 +286,6 @@ def main(): if os.path.isfile('/etc/debian_version'): # Show pull number on Debian default prompt os.putenv('debian_chroot',pull) subprocess.call([BASH,'-i']) - reply = ask_prompt("Type 'm' to accept the merge.") - if reply.lower() == 'm': - print("Merge accepted.",file=stderr) - else: - print("ERROR: Merge rejected.",file=stderr) - exit(7) second_sha512 = tree_sha512sum() if first_sha512 != second_sha512: @@ -303,16 +293,19 @@ def main(): exit(8) # Sign the merge commit. - reply = ask_prompt("Type 's' to sign off on the merge.") - if reply == 's': - try: - subprocess.check_call([GIT,'commit','-q','--gpg-sign','--amend','--no-edit']) - except subprocess.CalledProcessError as e: - print("Error signing, exiting.",file=stderr) + print_merge_details(pull, title, branch, base_branch, head_branch) + while True: + reply = ask_prompt("Type 's' to sign off on the above merge, or 'x' to reject and exit.").lower() + if reply == 's': + try: + subprocess.check_call([GIT,'commit','-q','--gpg-sign','--amend','--no-edit']) + break + except subprocess.CalledProcessError as e: + print("Error signing, exiting.",file=stderr) + exit(1) + elif reply == 'x': + print("Not signing off on merge, exiting.",file=stderr) exit(1) - else: - print("Not signing off on merge, exiting.",file=stderr) - exit(1) # Put the result in branch. subprocess.check_call([GIT,'checkout','-q',branch]) @@ -326,9 +319,13 @@ def main(): subprocess.call([GIT,'branch','-q','-D',local_merge_branch],stderr=devnull) # Push the result. - reply = ask_prompt("Type 'push' to push the result to %s, branch %s." % (host_repo,branch)) - if reply.lower() == 'push': - subprocess.check_call([GIT,'push',host_repo,'refs/heads/'+branch]) + while True: + reply = ask_prompt("Type 'push' to push the result to %s, branch %s, or 'x' to exit without pushing." % (host_repo,branch)).lower() + if reply == 'push': + subprocess.check_call([GIT,'push',host_repo,'refs/heads/'+branch]) + break + elif reply == 'x': + exit(1) if __name__ == '__main__': main() From 0d2f2b36178ace7a0d710666bf444931f100c245 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 26 Apr 2017 10:27:25 +0200 Subject: [PATCH 042/987] Merge #10273: [scripts] Minor improvements to `macdeployqtplus` script. e8babc4 Use `with` in `macdeployqtplus` script. (Chris Gavin) 4f3ac7d Remove unused variable from `macdeployqtplus` script. (Chris Gavin) Tree-SHA512: 0259506b36f3bfcc64ada951dcd4fdab1611ef76a39f92effd1163b6d8fab06bdbf50784b4b22f8b1483697c3029c12cfee5372b442ab445887ac4f928f6de80 --- contrib/macdeploy/macdeployqtplus | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contrib/macdeploy/macdeployqtplus b/contrib/macdeploy/macdeployqtplus index 7a22d99bbc6c..4207cb7319b0 100755 --- a/contrib/macdeploy/macdeployqtplus +++ b/contrib/macdeploy/macdeployqtplus @@ -301,7 +301,6 @@ def copyFramework(framework, path, verbose): if os.path.exists(fromContentsDir): toContentsDir = os.path.join(path, framework.destinationVersionContentsDirectory) shutil.copytree(fromContentsDir, toContentsDir, symlinks=True) - contentslinkfrom = os.path.join(path, framework.destinationContentsDirectory) if verbose >= 3: print("Copied Contents:", fromContentsDir) print(" to:", toContentsDir) @@ -674,9 +673,8 @@ else: if verbose >= 2: print("+ Installing qt.conf +") -f = open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") -f.write(qt_conf.encode()) -f.close() +with open(os.path.join(applicationBundle.resourcesPath, "qt.conf"), "wb") as f: + f.write(qt_conf.encode()) # ------------------------------------------------ From 55dc3dae52877fd5a1cfeaa69b08db61d4ef675d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 1 Jun 2017 10:42:13 +0200 Subject: [PATCH 043/987] Merge #10486: devtools: Retry after signing fails in github-merge 1983c87 devtools: Retry after signing fails in github-merge (Wladimir J. van der Laan) Tree-SHA512: f5ef91c93f4e53c9b234e7dc3ac398c6715144021d92c8592174d02c672ae99d27e88faefd52239c2a74c8e49cfd3a979e0229580016ce9a74829bdb0af206ec --- contrib/devtools/github-merge.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py index 03ccf5b62411..a96bb7a6ba30 100755 --- a/contrib/devtools/github-merge.py +++ b/contrib/devtools/github-merge.py @@ -301,8 +301,7 @@ def main(): subprocess.check_call([GIT,'commit','-q','--gpg-sign','--amend','--no-edit']) break except subprocess.CalledProcessError as e: - print("Error signing, exiting.",file=stderr) - exit(1) + print("Error while signing, asking again.",file=stderr) elif reply == 'x': print("Not signing off on merge, exiting.",file=stderr) exit(1) From b708ea819ae83d0bf045b5180c315c94866da35b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 1 Jun 2017 13:19:27 +0200 Subject: [PATCH 044/987] Merge #10469: Fixing typo in rpcdump.cpp 16d94d3 Fixing typo in rpcdump.cpp (James Evans) Tree-SHA512: 84ef1b91c719131196ebed6b865e282b77bee7699614e15884ba59010239a3bbc1380dc8f856c83338f071e3eb3ca41c6b10f830816e6c794531cf6a965d63a9 --- src/wallet/rpcdump.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index a054c09f465b..a50abea43623 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -333,7 +333,7 @@ UniValue removeprunedfunds(const JSONRPCRequest& request) if (request.fHelp || request.params.size() != 1) throw std::runtime_error( "removeprunedfunds \"txid\"\n" - "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will effect wallet balances.\n" + "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n" "\nArguments:\n" "1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n" "\nExamples:\n" From f5706315563c5b20d742bfe6445c4b00469f54a3 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 5 Jun 2017 16:05:15 +0200 Subject: [PATCH 045/987] Merge #10514: Bugfix: missing == 0 after randrange 9aa215b Bugfixes: missing == 0 after randrange (Pieter Wuille) Tree-SHA512: 160657ac09553f23ad7a3966c753a30ba938ce6f7ccfd34a4ef0d05d73d712362f7eef97e44a96e37a181b8347caa9d8e1584cc4485f69674ab2de3d8a247373 --- src/test/coins_tests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 5220e343823e..42ab30431a2a 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -181,7 +181,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // One every 10 iterations, remove a random entry from the cache - if (insecure_rand() % 10) { + if (insecure_rand() % 10 == 0) { COutPoint out(txids[insecure_rand() % txids.size()], 0); int cacheid = insecure_rand() % stack.size(); stack[cacheid]->Uncache(out); @@ -430,13 +430,13 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // One every 10 iterations, remove a random entry from the cache - if (utxoset.size() > 1 && insecure_rand() % 30) { + if (utxoset.size() > 1 && insecure_rand() % 30 == 0) { stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); } - if (disconnected_coins.size() > 1 && insecure_rand() % 30) { + if (disconnected_coins.size() > 1 && insecure_rand() % 30 == 0) { stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); } - if (duplicate_coins.size() > 1 && insecure_rand() % 30) { + if (duplicate_coins.size() > 1 && insecure_rand() % 30 == 0) { stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); } From 31bb4622a668458680268b55064dda2681410538 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 6 Jun 2017 23:46:16 +0200 Subject: [PATCH 046/987] Merge #10538: [trivial] Fix typo: "occurrences" (misspelled as "occurrances") b083db6 [trivial] Fix typo: "occurrences" (misspelled as "occurrances") (practicalswift) Tree-SHA512: 5141526dbbbbe797ef103fcbdc0a1318648214973214607e35cc0e99abfc4dd547e3ef15fe21976c53a78b03dff140fe76e5c92a0f7e7d2b08081215983a8616 --- src/coins.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coins.cpp b/src/coins.cpp index 1f8baa2b1ba1..801b94d79cd8 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -91,7 +91,7 @@ void AddCoins(CCoinsViewCache& cache, const CTransaction &tx, int nHeight) { const uint256& txid = tx.GetHash(); for (size_t i = 0; i < tx.vout.size(); ++i) { // Pass fCoinbase as the possible_overwrite flag to AddCoin, in order to correctly - // deal with the pre-BIP30 occurrances of duplicate coinbase transactions. + // deal with the pre-BIP30 occurrences of duplicate coinbase transactions. cache.AddCoin(COutPoint(txid, i), Coin(tx.vout[i], nHeight, fCoinbase), fCoinbase); } } From 742744f25f494759f1e7c71bc05be3657d531dc9 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 6 Jun 2017 23:51:30 +0200 Subject: [PATCH 047/987] Merge #10522: [wallet] Remove unused variables a8c09af Remove unused variables (practicalswift) Tree-SHA512: 34807dc3a0471c83b086f430b66465602c8f6a3a158b54ace2ec8afb746f1f5907f7dfcde5a4bad4041df9721ec46b61681b2dbf89725c9c8c4c5ad0ca99f78f --- src/wallet/db.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 4d85d445ee3c..199c8402f67c 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -211,7 +211,6 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco { CDataStream ssKey(row.first, SER_DISK, CLIENT_VERSION); CDataStream ssValue(row.second, SER_DISK, CLIENT_VERSION); - std::string strType, strErr; if (!(*recoverKVcallback)(callbackDataIn, ssKey, ssValue)) continue; } From eecc724362d1a5450dca1d4cba77ceda05999fc1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 12 Jun 2017 15:40:18 -0700 Subject: [PATCH 048/987] Merge #10564: Return early in IsBanned. bf376eacc Return early in IsBanned. (Gregory Maxwell) Tree-SHA512: d8ed4aaf9a7523b00effa4ac17cec3be1ec1f5c5ce64d89833fbc8f3d73d13b022043354fbcf2682b2af05070d115e1fc0cc0b122197e9ddee5959c3fb9dd16d --- src/net.cpp | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index e65a35fabca0..13a3efa232d9 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -467,35 +467,31 @@ void CConnman::ClearBanned() bool CConnman::IsBanned(CNetAddr ip) { - bool fResult = false; + LOCK(cs_setBanned); + for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++) { - LOCK(cs_setBanned); - for (banmap_t::iterator it = setBanned.begin(); it != setBanned.end(); it++) - { - CSubNet subNet = (*it).first; - CBanEntry banEntry = (*it).second; + CSubNet subNet = (*it).first; + CBanEntry banEntry = (*it).second; - if(subNet.Match(ip) && GetTime() < banEntry.nBanUntil) - fResult = true; + if (subNet.Match(ip) && GetTime() < banEntry.nBanUntil) { + return true; } } - return fResult; + return false; } bool CConnman::IsBanned(CSubNet subnet) { - bool fResult = false; + LOCK(cs_setBanned); + banmap_t::iterator i = setBanned.find(subnet); + if (i != setBanned.end()) { - LOCK(cs_setBanned); - banmap_t::iterator i = setBanned.find(subnet); - if (i != setBanned.end()) - { - CBanEntry banEntry = (*i).second; - if (GetTime() < banEntry.nBanUntil) - fResult = true; + CBanEntry banEntry = (*i).second; + if (GetTime() < banEntry.nBanUntil) { + return true; } } - return fResult; + return false; } void CConnman::Ban(const CNetAddr& addr, const BanReason &banReason, int64_t bantimeoffset, bool sinceUnixEpoch) { From e7a21faa2b1e2e224d49a1ed362c1eefb192f7ca Mon Sep 17 00:00:00 2001 From: NicolasDorier Date: Sun, 12 May 2019 00:12:59 -0500 Subject: [PATCH 049/987] Merge Bitcoin#9960: Trivial: Add const modifier to GetHDChain and IsHDEnabled Signed-off-by: Pasta --- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 072250247976..9f7d84769def 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1604,7 +1604,7 @@ bool CWallet::GetDecryptedHDChain(CHDChain& hdChainRet) return true; } -bool CWallet::IsHDEnabled() +bool CWallet::IsHDEnabled() const { CHDChain hdChainCurrent; return GetHDChain(hdChainCurrent); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 26095893b95f..1884f7b9da1b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1164,7 +1164,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface */ /* Returns true if HD is enabled */ - bool IsHDEnabled(); + bool IsHDEnabled() const; /* Generates a new HD chain */ void GenerateNewHDChain(); /* Set the HD chain model (chain child index counters) */ From 2f63322cdc1ec003ea5e0a12a84dc8327bd645fc Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 15 May 2019 21:21:54 -0500 Subject: [PATCH 050/987] dashify "Finding reviewers" section to be more relevant Signed-off-by: Pasta --- CONTRIBUTING.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9b77c54cc8c..e8ce37f96780 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -227,11 +227,10 @@ a worthwhile change based on the judgement of the maintainers. ### Finding Reviewers -As most reviewers are themselves developers with their own projects, the review -process can be quite lengthy, and some amount of patience is required. If you find -that you've been waiting for a pull request to be given attention for several -months, there may be a number of reasons for this, some of which you can do something -about: +The review process is normally fairly responsive on the Dash Core repository, however +this might not always be the case. If you find that you've been waiting +for a pull request to be given attention for several months, there may be a number +of reasons for this, some of which you can do something about: - It may be because of a feature freeze due to an upcoming release. During this time, only bug fixes are taken into consideration. If your pull request is a new feature, @@ -243,15 +242,15 @@ about: that personally, though! Instead, take another critical look at what you are suggesting and see if it: changes too much, is too broad, doesn't adhere to the [developer notes](doc/developer-notes.md), is dangerous or insecure, is messily written, etc. - Identify and address any of the issues you find. Then ask e.g. on IRC if someone could give - their opinion on the concept itself. + Identify and address any of the issues you find. Then ask e.g. on the forum or on a community + discord if someone could give their opinion on the concept itself. - It may be because your code is too complex for all but a few people. And those people may not have realized your pull request even exists. A great way to find people who are qualified and care about the code you are touching is the [Git Blame feature](https://help.github.com/articles/tracing-changes-in-a-file/). Simply find the person touching the code you are touching before you and see if you can find them and give them a nudge. Don't be incessant about the nudging though. - - Finally, if all else fails, ask on IRC or elsewhere for someone to give your pull request + - Finally, if all else fails, ask on discord or elsewhere for someone to give your pull request a look. If you think you've been waiting an unreasonably long amount of time (month+) for no particular reason (few lines changed, etc), this is totally fine. Try to return the favor when someone else is asking for feedback on their code, and universe balances out. From 67c735b1567f9d99907bf4fdf1e5d8e94f4c23d2 Mon Sep 17 00:00:00 2001 From: Pasta Date: Thu, 16 May 2019 09:57:15 -0500 Subject: [PATCH 051/987] s/bitcoin-config.h/dash-config.h/ Signed-off-by: Pasta --- src/Makefile.am | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 054122111776..4d793ccbf633 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -639,12 +639,12 @@ $(top_srcdir)/$(subdir)/config/dash-config.h.in: $(am__configure_deps) $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/dash-config.h.in -config/bitcoin-config.h: config/stamp-h1 +config/dash-config.h: config/stamp-h1 @$(MAKE) -C $(top_builddir) $(subdir)/$(@) -config/stamp-h1: $(top_srcdir)/$(subdir)/config/bitcoin-config.h.in $(top_builddir)/config.status +config/stamp-h1: $(top_srcdir)/$(subdir)/config/dash-config.h.in $(top_builddir)/config.status $(AM_V_at)$(MAKE) -C $(top_builddir) $(subdir)/$(@) -$(top_srcdir)/$(subdir)/config/bitcoin-config.h.in: $(am__configure_deps) - $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/bitcoin-config.h.in +$(top_srcdir)/$(subdir)/config/dash-config.h.in: $(am__configure_deps) + $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/dash-config.h.in clean-local: -$(MAKE) -C secp256k1 clean From 32aa229c7ff316d114e6abc6bbd1e6c179c3ea87 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Tue, 21 May 2019 08:26:15 -0500 Subject: [PATCH 052/987] Reorganize Dash Specific code into folders (#2753) * rename instantx.* file to instantsend.* * Reorganize Dash Specific code into folders add to privatesend folder the header files Signed-off-by: Pasta add "masternode" to imports Signed-off-by: Pasta add "masternode" to imports Signed-off-by: Pasta add "masternode" to imports pt 2 Signed-off-by: Pasta --- src/Makefile.am | 66 +++++++++---------- src/dsnotificationinterface.cpp | 12 ++-- src/evo/mnauth.cpp | 4 +- src/{ => governance}/governance-classes.cpp | 0 src/{ => governance}/governance-classes.h | 0 src/{ => governance}/governance-exceptions.h | 0 src/{ => governance}/governance-object.cpp | 6 +- src/{ => governance}/governance-object.h | 0 .../governance-validators.cpp | 0 src/{ => governance}/governance-validators.h | 0 src/{ => governance}/governance-vote.cpp | 2 +- src/{ => governance}/governance-vote.h | 0 src/{ => governance}/governance-votedb.cpp | 0 src/{ => governance}/governance-votedb.h | 0 src/{ => governance}/governance.cpp | 4 +- src/{ => governance}/governance.h | 0 src/init.cpp | 18 ++--- src/{instantx.cpp => instantsend.cpp} | 10 +-- src/{instantx.h => instantsend.h} | 0 src/llmq/quorums.cpp | 4 +- src/llmq/quorums_chainlocks.cpp | 2 +- src/llmq/quorums_dkgsession.cpp | 2 +- src/llmq/quorums_dkgsessionhandler.cpp | 2 +- src/llmq/quorums_instantsend.cpp | 4 +- src/llmq/quorums_signing.cpp | 2 +- src/llmq/quorums_signing_shares.cpp | 2 +- src/{ => masternode}/activemasternode.cpp | 2 +- src/{ => masternode}/activemasternode.h | 0 src/{ => masternode}/masternode-meta.cpp | 0 src/{ => masternode}/masternode-meta.h | 0 src/{ => masternode}/masternode-payments.cpp | 8 +-- src/{ => masternode}/masternode-payments.h | 0 src/{ => masternode}/masternode-sync.cpp | 8 +-- src/{ => masternode}/masternode-sync.h | 0 src/{ => masternode}/masternode-utils.cpp | 6 +- src/{ => masternode}/masternode-utils.h | 0 src/miner.cpp | 4 +- src/net.cpp | 6 +- src/net_processing.cpp | 14 ++-- src/{ => privatesend}/privatesend-client.cpp | 6 +- src/{ => privatesend}/privatesend-client.h | 0 src/{ => privatesend}/privatesend-server.cpp | 6 +- src/{ => privatesend}/privatesend-server.h | 0 src/{ => privatesend}/privatesend-util.cpp | 0 src/{ => privatesend}/privatesend-util.h | 0 src/{ => privatesend}/privatesend.cpp | 6 +- src/{ => privatesend}/privatesend.h | 0 src/qt/bitcoingui.cpp | 2 +- src/qt/clientmodel.cpp | 4 +- src/qt/coincontroldialog.cpp | 4 +- src/qt/masternodelist.cpp | 4 +- src/qt/optionsdialog.cpp | 2 +- src/qt/optionsmodel.cpp | 2 +- src/qt/overviewpage.cpp | 6 +- src/qt/sendcoinsdialog.cpp | 2 +- src/qt/transactiondesc.cpp | 2 +- src/qt/transactionrecord.cpp | 2 +- src/qt/walletmodel.cpp | 4 +- src/rpc/blockchain.cpp | 2 +- src/rpc/governance.cpp | 12 ++-- src/rpc/masternode.cpp | 10 +-- src/rpc/mining.cpp | 6 +- src/rpc/misc.cpp | 2 +- src/rpc/rawtransaction.cpp | 2 +- src/test/governance_validators_tests.cpp | 2 +- src/test/miner_tests.cpp | 2 +- src/test/ratecheck_tests.cpp | 2 +- src/txmempool.cpp | 2 +- src/validation.cpp | 4 +- src/wallet/rpcwallet.cpp | 4 +- src/wallet/wallet.cpp | 6 +- src/wallet/wallet.h | 2 +- src/zmq/zmqconfig.h | 6 +- 73 files changed, 152 insertions(+), 152 deletions(-) rename src/{ => governance}/governance-classes.cpp (100%) rename src/{ => governance}/governance-classes.h (100%) rename src/{ => governance}/governance-exceptions.h (100%) rename src/{ => governance}/governance-object.cpp (99%) rename src/{ => governance}/governance-object.h (100%) rename src/{ => governance}/governance-validators.cpp (100%) rename src/{ => governance}/governance-validators.h (100%) rename src/{ => governance}/governance-vote.cpp (99%) rename src/{ => governance}/governance-vote.h (100%) rename src/{ => governance}/governance-votedb.cpp (100%) rename src/{ => governance}/governance-votedb.h (100%) rename src/{ => governance}/governance.cpp (99%) rename src/{ => governance}/governance.h (100%) rename src/{instantx.cpp => instantsend.cpp} (99%) rename src/{instantx.h => instantsend.h} (100%) rename src/{ => masternode}/activemasternode.cpp (99%) rename src/{ => masternode}/activemasternode.h (100%) rename src/{ => masternode}/masternode-meta.cpp (100%) rename src/{ => masternode}/masternode-meta.h (100%) rename src/{ => masternode}/masternode-payments.cpp (99%) rename src/{ => masternode}/masternode-payments.h (100%) rename src/{ => masternode}/masternode-sync.cpp (99%) rename src/{ => masternode}/masternode-sync.h (100%) rename src/{ => masternode}/masternode-utils.cpp (96%) rename src/{ => masternode}/masternode-utils.h (100%) rename src/{ => privatesend}/privatesend-client.cpp (99%) rename src/{ => privatesend}/privatesend-client.h (100%) rename src/{ => privatesend}/privatesend-server.cpp (99%) rename src/{ => privatesend}/privatesend-server.h (100%) rename src/{ => privatesend}/privatesend-util.cpp (100%) rename src/{ => privatesend}/privatesend-util.h (100%) rename src/{ => privatesend}/privatesend.cpp (99%) rename src/{ => privatesend}/privatesend.h (100%) diff --git a/src/Makefile.am b/src/Makefile.am index de6b93991ff2..7aa6a2fbd254 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -102,7 +102,6 @@ endif # dash core # BITCOIN_CORE_H = \ addrdb.h \ - activemasternode.h \ addressindex.h \ spentindex.h \ addrman.h \ @@ -141,25 +140,25 @@ BITCOIN_CORE_H = \ evo/providertx.h \ evo/simplifiedmns.h \ evo/specialtx.h \ - privatesend.h \ - privatesend-client.h \ - privatesend-server.h \ - privatesend-util.h \ + privatesend/privatesend.h \ + privatesend/privatesend-client.h \ + privatesend/privatesend-server.h \ + privatesend/privatesend-util.h \ dsnotificationinterface.h \ - governance.h \ - governance-classes.h \ - governance-exceptions.h \ - governance-object.h \ - governance-validators.h \ - governance-vote.h \ - governance-votedb.h \ + governance/governance.h \ + governance/governance-classes.h \ + governance/governance-exceptions.h \ + governance/governance-object.h \ + governance/governance-validators.h \ + governance/governance-vote.h \ + governance/governance-votedb.h \ flat-database.h \ hdchain.h \ httprpc.h \ httpserver.h \ indirectmap.h \ init.h \ - instantx.h \ + instantsend.h \ key.h \ keepass.h \ keystore.h \ @@ -178,10 +177,11 @@ BITCOIN_CORE_H = \ llmq/quorums_signing.h \ llmq/quorums_signing_shares.h \ llmq/quorums_utils.h \ - masternode-meta.h \ - masternode-payments.h \ - masternode-sync.h \ - masternode-utils.h \ + masternode/activemasternode.h \ + masternode/masternode-meta.h \ + masternode/masternode-payments.h \ + masternode/masternode-sync.h \ + masternode/masternode-utils.h \ memusage.h \ merkleblock.h \ messagesigner.h \ @@ -258,7 +258,6 @@ libdash_util_a-clientversion.$(OBJEXT): obj/build.h libdash_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libdash_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libdash_server_a_SOURCES = \ - activemasternode.cpp \ addrman.cpp \ addrdb.cpp \ alert.cpp \ @@ -278,14 +277,14 @@ libdash_server_a_SOURCES = \ httprpc.cpp \ httpserver.cpp \ init.cpp \ - instantx.cpp \ + instantsend.cpp \ dbwrapper.cpp \ - governance.cpp \ - governance-classes.cpp \ - governance-object.cpp \ - governance-validators.cpp \ - governance-vote.cpp \ - governance-votedb.cpp \ + governance/governance.cpp \ + governance/governance-classes.cpp \ + governance/governance-object.cpp \ + governance/governance-validators.cpp \ + governance/governance-vote.cpp \ + governance/governance-votedb.cpp \ llmq/quorums.cpp \ llmq/quorums_blockprocessor.cpp \ llmq/quorums_commitment.cpp \ @@ -299,10 +298,11 @@ libdash_server_a_SOURCES = \ llmq/quorums_signing.cpp \ llmq/quorums_signing_shares.cpp \ llmq/quorums_utils.cpp \ - masternode-meta.cpp \ - masternode-payments.cpp \ - masternode-sync.cpp \ - masternode-utils.cpp \ + masternode/activemasternode.cpp \ + masternode/masternode-meta.cpp \ + masternode/masternode-payments.cpp \ + masternode/masternode-sync.cpp \ + masternode/masternode-utils.cpp \ merkleblock.cpp \ messagesigner.cpp \ miner.cpp \ @@ -313,8 +313,8 @@ libdash_server_a_SOURCES = \ policy/fees.cpp \ policy/policy.cpp \ pow.cpp \ - privatesend.cpp \ - privatesend-server.cpp \ + privatesend/privatesend.cpp \ + privatesend/privatesend-server.cpp \ rest.cpp \ rpc/blockchain.cpp \ rpc/masternode.cpp \ @@ -356,8 +356,8 @@ libdash_wallet_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libdash_wallet_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libdash_wallet_a_SOURCES = \ keepass.cpp \ - privatesend-client.cpp \ - privatesend-util.cpp \ + privatesend/privatesend-client.cpp \ + privatesend/privatesend-util.cpp \ wallet/crypter.cpp \ wallet/db.cpp \ wallet/rpcdump.cpp \ diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index e4c174336d1e..9bcf1e3ea16a 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -4,13 +4,13 @@ #include "chainparams.h" #include "dsnotificationinterface.h" -#include "instantx.h" -#include "governance.h" -#include "masternode-payments.h" -#include "masternode-sync.h" -#include "privatesend.h" +#include "instantsend.h" +#include "governance/governance.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" +#include "privatesend/privatesend.h" #ifdef ENABLE_WALLET -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #endif // ENABLE_WALLET #include "validation.h" diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 4810f88239f9..7592d24cb13d 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -4,9 +4,9 @@ #include "mnauth.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "evo/deterministicmns.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "net.h" #include "net_processing.h" #include "netmessagemaker.h" diff --git a/src/governance-classes.cpp b/src/governance/governance-classes.cpp similarity index 100% rename from src/governance-classes.cpp rename to src/governance/governance-classes.cpp diff --git a/src/governance-classes.h b/src/governance/governance-classes.h similarity index 100% rename from src/governance-classes.h rename to src/governance/governance-classes.h diff --git a/src/governance-exceptions.h b/src/governance/governance-exceptions.h similarity index 100% rename from src/governance-exceptions.h rename to src/governance/governance-exceptions.h diff --git a/src/governance-object.cpp b/src/governance/governance-object.cpp similarity index 99% rename from src/governance-object.cpp rename to src/governance/governance-object.cpp index 0b9cbe0878c5..e539c18d5ded 100644 --- a/src/governance-object.cpp +++ b/src/governance/governance-object.cpp @@ -8,9 +8,9 @@ #include "governance-validators.h" #include "governance-vote.h" #include "governance.h" -#include "instantx.h" -#include "masternode-meta.h" -#include "masternode-sync.h" +#include "instantsend.h" +#include "masternode/masternode-meta.h" +#include "masternode/masternode-sync.h" #include "messagesigner.h" #include "spork.h" #include "util.h" diff --git a/src/governance-object.h b/src/governance/governance-object.h similarity index 100% rename from src/governance-object.h rename to src/governance/governance-object.h diff --git a/src/governance-validators.cpp b/src/governance/governance-validators.cpp similarity index 100% rename from src/governance-validators.cpp rename to src/governance/governance-validators.cpp diff --git a/src/governance-validators.h b/src/governance/governance-validators.h similarity index 100% rename from src/governance-validators.h rename to src/governance/governance-validators.h diff --git a/src/governance-vote.cpp b/src/governance/governance-vote.cpp similarity index 99% rename from src/governance-vote.cpp rename to src/governance/governance-vote.cpp index deea595def79..81555fb9d6b6 100644 --- a/src/governance-vote.cpp +++ b/src/governance/governance-vote.cpp @@ -4,7 +4,7 @@ #include "governance-vote.h" #include "governance-object.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "messagesigner.h" #include "spork.h" #include "util.h" diff --git a/src/governance-vote.h b/src/governance/governance-vote.h similarity index 100% rename from src/governance-vote.h rename to src/governance/governance-vote.h diff --git a/src/governance-votedb.cpp b/src/governance/governance-votedb.cpp similarity index 100% rename from src/governance-votedb.cpp rename to src/governance/governance-votedb.cpp diff --git a/src/governance-votedb.h b/src/governance/governance-votedb.h similarity index 100% rename from src/governance-votedb.h rename to src/governance/governance-votedb.h diff --git a/src/governance.cpp b/src/governance/governance.cpp similarity index 99% rename from src/governance.cpp rename to src/governance/governance.cpp index 9b2b98af5d72..6dcadfa4f1df 100644 --- a/src/governance.cpp +++ b/src/governance/governance.cpp @@ -9,8 +9,8 @@ #include "governance-validators.h" #include "governance-vote.h" #include "init.h" -#include "masternode-meta.h" -#include "masternode-sync.h" +#include "masternode/masternode-meta.h" +#include "masternode/masternode-sync.h" #include "messagesigner.h" #include "net_processing.h" #include "netfulfilledman.h" diff --git a/src/governance.h b/src/governance/governance.h similarity index 100% rename from src/governance.h rename to src/governance/governance.h diff --git a/src/init.cpp b/src/init.cpp index 65101215625f..1732b2eae051 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -44,24 +44,24 @@ #include "wallet/wallet.h" #endif -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "dsnotificationinterface.h" #include "flat-database.h" -#include "governance.h" -#include "instantx.h" +#include "governance/governance.h" +#include "instantsend.h" #ifdef ENABLE_WALLET #include "keepass.h" #endif -#include "masternode-meta.h" -#include "masternode-payments.h" -#include "masternode-sync.h" -#include "masternode-utils.h" +#include "masternode/masternode-meta.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" +#include "masternode/masternode-utils.h" #include "messagesigner.h" #include "netfulfilledman.h" #ifdef ENABLE_WALLET -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #endif // ENABLE_WALLET -#include "privatesend-server.h" +#include "privatesend/privatesend-server.h" #include "spork.h" #include "warnings.h" diff --git a/src/instantx.cpp b/src/instantsend.cpp similarity index 99% rename from src/instantx.cpp rename to src/instantsend.cpp index b43041c4ee0c..85b4cadc339a 100644 --- a/src/instantx.cpp +++ b/src/instantsend.cpp @@ -2,14 +2,14 @@ // 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 "masternode/activemasternode.h" #include "init.h" -#include "instantx.h" +#include "instantsend.h" #include "key.h" #include "validation.h" -#include "masternode-payments.h" -#include "masternode-sync.h" -#include "masternode-utils.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" +#include "masternode/masternode-utils.h" #include "messagesigner.h" #include "net.h" #include "netmessagemaker.h" diff --git a/src/instantx.h b/src/instantsend.h similarity index 100% rename from src/instantx.h rename to src/instantsend.h diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 201b286df1f5..807db05df2dc 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -12,10 +12,10 @@ #include "evo/specialtx.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "chainparams.h" #include "init.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "univalue.h" #include "validation.h" diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 6e377c221038..ffa60866140a 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -9,7 +9,7 @@ #include "quorums_utils.h" #include "chain.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "net_processing.h" #include "scheduler.h" #include "spork.h" diff --git a/src/llmq/quorums_dkgsession.cpp b/src/llmq/quorums_dkgsession.cpp index ab844f5f6ec5..693a03f2e25b 100644 --- a/src/llmq/quorums_dkgsession.cpp +++ b/src/llmq/quorums_dkgsession.cpp @@ -11,7 +11,7 @@ #include "evo/specialtx.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "chainparams.h" #include "init.h" #include "net.h" diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index eb60d81d4668..b00904ab4559 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -8,7 +8,7 @@ #include "quorums_init.h" #include "quorums_utils.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "chainparams.h" #include "init.h" #include "net_processing.h" diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 13aa7a3c9194..dd926430904c 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -10,7 +10,7 @@ #include "chainparams.h" #include "coins.h" #include "txmempool.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "net_processing.h" #include "spork.h" #include "validation.h" @@ -20,7 +20,7 @@ #endif // needed for AUTO_IX_MEMPOOL_THRESHOLD -#include "instantx.h" +#include "instantsend.h" #include #include diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index 98dd0926424d..ad9639a562a8 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -6,7 +6,7 @@ #include "quorums_utils.h" #include "quorums_signing_shares.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "bls/bls_batchverifier.h" #include "cxxtimer.hpp" #include "init.h" diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index 4e9103d5b997..89ea8689770a 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -6,7 +6,7 @@ #include "quorums_signing_shares.h" #include "quorums_utils.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "bls/bls_batchverifier.h" #include "init.h" #include "net_processing.h" diff --git a/src/activemasternode.cpp b/src/masternode/activemasternode.cpp similarity index 99% rename from src/activemasternode.cpp rename to src/masternode/activemasternode.cpp index 3484c16eb043..e0278b761ec4 100644 --- a/src/activemasternode.cpp +++ b/src/masternode/activemasternode.cpp @@ -5,7 +5,7 @@ #include "activemasternode.h" #include "evo/deterministicmns.h" #include "init.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "netbase.h" #include "protocol.h" #include "validation.h" diff --git a/src/activemasternode.h b/src/masternode/activemasternode.h similarity index 100% rename from src/activemasternode.h rename to src/masternode/activemasternode.h diff --git a/src/masternode-meta.cpp b/src/masternode/masternode-meta.cpp similarity index 100% rename from src/masternode-meta.cpp rename to src/masternode/masternode-meta.cpp diff --git a/src/masternode-meta.h b/src/masternode/masternode-meta.h similarity index 100% rename from src/masternode-meta.h rename to src/masternode/masternode-meta.h diff --git a/src/masternode-payments.cpp b/src/masternode/masternode-payments.cpp similarity index 99% rename from src/masternode-payments.cpp rename to src/masternode/masternode-payments.cpp index d71b15df7cac..d6e2af5f6aee 100644 --- a/src/masternode-payments.cpp +++ b/src/masternode/masternode-payments.cpp @@ -2,12 +2,12 @@ // 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 "masternode/activemasternode.h" #include "consensus/validation.h" -#include "governance-classes.h" +#include "governance/governance-classes.h" #include "init.h" -#include "masternode-payments.h" -#include "masternode-sync.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" #include "messagesigner.h" #include "netfulfilledman.h" #include "netmessagemaker.h" diff --git a/src/masternode-payments.h b/src/masternode/masternode-payments.h similarity index 100% rename from src/masternode-payments.h rename to src/masternode/masternode-payments.h diff --git a/src/masternode-sync.cpp b/src/masternode/masternode-sync.cpp similarity index 99% rename from src/masternode-sync.cpp rename to src/masternode/masternode-sync.cpp index 5f5744a3aa7d..1dea1bba8bf3 100644 --- a/src/masternode-sync.cpp +++ b/src/masternode/masternode-sync.cpp @@ -2,12 +2,12 @@ // 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 "governance.h" +#include "masternode/activemasternode.h" +#include "governance/governance.h" #include "init.h" #include "validation.h" -#include "masternode-payments.h" -#include "masternode-sync.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" #include "netfulfilledman.h" #include "netmessagemaker.h" #include "ui_interface.h" diff --git a/src/masternode-sync.h b/src/masternode/masternode-sync.h similarity index 100% rename from src/masternode-sync.h rename to src/masternode/masternode-sync.h diff --git a/src/masternode-utils.cpp b/src/masternode/masternode-utils.cpp similarity index 96% rename from src/masternode-utils.cpp rename to src/masternode/masternode-utils.cpp index 9d4605086711..f199fc78b520 100644 --- a/src/masternode-utils.cpp +++ b/src/masternode/masternode-utils.cpp @@ -2,12 +2,12 @@ // 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 "masternode/masternode-utils.h" #include "init.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #ifdef ENABLE_WALLET -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #endif #include "validation.h" diff --git a/src/masternode-utils.h b/src/masternode/masternode-utils.h similarity index 100% rename from src/masternode-utils.h rename to src/masternode/masternode-utils.h diff --git a/src/miner.cpp b/src/miner.cpp index db456b624895..dd039148368a 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -24,8 +24,8 @@ #include "txmempool.h" #include "util.h" #include "utilmoneystr.h" -#include "masternode-payments.h" -#include "masternode-sync.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" #include "validationinterface.h" #include "evo/specialtx.h" diff --git a/src/net.cpp b/src/net.cpp index e65a35fabca0..dc6ef070de50 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -25,9 +25,9 @@ #include "utilstrencodings.h" #include "validation.h" -#include "instantx.h" -#include "masternode-sync.h" -#include "privatesend.h" +#include "instantsend.h" +#include "masternode/masternode-sync.h" +#include "privatesend/privatesend.h" #include "llmq/quorums_instantsend.h" #ifdef WIN32 diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 1df626b70fd0..97e43c088394 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -32,15 +32,15 @@ #include "validationinterface.h" #include "spork.h" -#include "governance.h" -#include "instantx.h" -#include "masternode-payments.h" -#include "masternode-sync.h" -#include "masternode-meta.h" +#include "governance/governance.h" +#include "instantsend.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" +#include "masternode/masternode-meta.h" #ifdef ENABLE_WALLET -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #endif // ENABLE_WALLET -#include "privatesend-server.h" +#include "privatesend/privatesend-server.h" #include "evo/deterministicmns.h" #include "evo/mnauth.h" diff --git a/src/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp similarity index 99% rename from src/privatesend-client.cpp rename to src/privatesend/privatesend-client.cpp index 24ad5d57ebb6..49076ec769fb 100644 --- a/src/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -7,9 +7,9 @@ #include "consensus/validation.h" #include "core_io.h" #include "init.h" -#include "masternode-payments.h" -#include "masternode-sync.h" -#include "masternode-meta.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" +#include "masternode/masternode-meta.h" #include "netmessagemaker.h" #include "script/sign.h" #include "txmempool.h" diff --git a/src/privatesend-client.h b/src/privatesend/privatesend-client.h similarity index 100% rename from src/privatesend-client.h rename to src/privatesend/privatesend-client.h diff --git a/src/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp similarity index 99% rename from src/privatesend-server.cpp rename to src/privatesend/privatesend-server.cpp index 761ec9e1f01f..8b3771a0d0e2 100644 --- a/src/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -4,12 +4,12 @@ #include "privatesend-server.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "consensus/validation.h" #include "core_io.h" #include "init.h" -#include "masternode-meta.h" -#include "masternode-sync.h" +#include "masternode/masternode-meta.h" +#include "masternode/masternode-sync.h" #include "net_processing.h" #include "netmessagemaker.h" #include "script/interpreter.h" diff --git a/src/privatesend-server.h b/src/privatesend/privatesend-server.h similarity index 100% rename from src/privatesend-server.h rename to src/privatesend/privatesend-server.h diff --git a/src/privatesend-util.cpp b/src/privatesend/privatesend-util.cpp similarity index 100% rename from src/privatesend-util.cpp rename to src/privatesend/privatesend-util.cpp diff --git a/src/privatesend-util.h b/src/privatesend/privatesend-util.h similarity index 100% rename from src/privatesend-util.h rename to src/privatesend/privatesend-util.h diff --git a/src/privatesend.cpp b/src/privatesend/privatesend.cpp similarity index 99% rename from src/privatesend.cpp rename to src/privatesend/privatesend.cpp index f96f0dfba0ba..654e6e4cc917 100644 --- a/src/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -4,10 +4,10 @@ #include "privatesend.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "consensus/validation.h" -#include "masternode-payments.h" -#include "masternode-sync.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" #include "messagesigner.h" #include "netmessagemaker.h" #include "script/sign.h" diff --git a/src/privatesend.h b/src/privatesend/privatesend.h similarity index 100% rename from src/privatesend.h rename to src/privatesend/privatesend.h diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 065ebf2e7362..b8d5790388aa 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -36,7 +36,7 @@ #include "init.h" #include "ui_interface.h" #include "util.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "masternodelist.h" #include diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 1ba75e691273..b8db9017399b 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -20,8 +20,8 @@ #include "ui_interface.h" #include "util.h" -#include "masternode-sync.h" -#include "privatesend.h" +#include "masternode/masternode-sync.h" +#include "privatesend/privatesend.h" #include diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index c7d57572ff8e..d6b555c85331 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -20,8 +20,8 @@ #include "validation.h" // For mempool #include "wallet/wallet.h" -#include "instantx.h" -#include "privatesend-client.h" +#include "instantsend.h" +#include "privatesend/privatesend-client.h" #include // for 'map_list_of()' diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp index b1f04036e66b..4cc0decd796c 100644 --- a/src/qt/masternodelist.cpp +++ b/src/qt/masternodelist.cpp @@ -1,12 +1,12 @@ #include "masternodelist.h" #include "ui_masternodelist.h" -#include "activemasternode.h" +#include "masternode/activemasternode.h" #include "clientmodel.h" #include "clientversion.h" #include "guiutil.h" #include "init.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "netbase.h" #include "sync.h" #include "wallet/wallet.h" diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index b8b1d1e37fad..8da87198403e 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -20,7 +20,7 @@ #ifdef ENABLE_WALLET #include "wallet/wallet.h" // for CWallet::GetRequiredFee() -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #endif // ENABLE_WALLET #include diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index e749e3eae6e4..2d614f7551b9 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -23,7 +23,7 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #endif #include diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 48a890d4740e..1a8f7e0e55cc 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -18,9 +18,9 @@ #include "utilitydialog.h" #include "walletmodel.h" -#include "instantx.h" -#include "masternode-sync.h" -#include "privatesend-client.h" +#include "instantsend.h" +#include "masternode/masternode-sync.h" +#include "privatesend/privatesend-client.h" #include #include diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 43fde4cd7a26..091b4c3afcd0 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -23,7 +23,7 @@ #include "txmempool.h" #include "wallet/wallet.h" -#include "privatesend.h" +#include "privatesend/privatesend.h" #include #include diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 1283cfa9313d..5e823d666292 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -19,7 +19,7 @@ #include "wallet/db.h" #include "wallet/wallet.h" -#include "instantx.h" +#include "instantsend.h" #include #include diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index f5ef21409323..88e1bcfd555a 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -11,7 +11,7 @@ #include "timedata.h" #include "wallet/wallet.h" -#include "privatesend.h" +#include "privatesend/privatesend.h" #include diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index e7ac33cb0b81..ca518b8ceb9f 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -23,9 +23,9 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" // for BackupWallet -#include "instantx.h" +#include "instantsend.h" #include "spork.h" -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #include "llmq/quorums_instantsend.h" #include diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index d08d518108fc..e303f1393178 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -11,7 +11,7 @@ #include "coins.h" #include "core_io.h" #include "consensus/validation.h" -#include "instantx.h" +#include "instantsend.h" #include "validation.h" #include "policy/policy.h" #include "primitives/transaction.h" diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 5b9d14415ed8..7a573de36d82 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -2,15 +2,15 @@ // 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 "masternode/activemasternode.h" #include "consensus/validation.h" -#include "governance.h" -#include "governance-vote.h" -#include "governance-classes.h" -#include "governance-validators.h" +#include "governance/governance.h" +#include "governance/governance-vote.h" +#include "governance/governance-classes.h" +#include "governance/governance-validators.h" #include "init.h" #include "validation.h" -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "messagesigner.h" #include "rpc/server.h" #include "util.h" diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index d04f1e62a26c..8734e0af87ee 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -2,18 +2,18 @@ // 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 "masternode/activemasternode.h" #include "base58.h" #include "clientversion.h" #include "init.h" #include "netbase.h" #include "validation.h" -#include "masternode-payments.h" -#include "masternode-sync.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" #ifdef ENABLE_WALLET -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #endif // ENABLE_WALLET -#include "privatesend-server.h" +#include "privatesend/privatesend-server.h" #include "rpc/server.h" #include "util.h" #include "utilmoneystr.h" diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 1d3ea083f35a..435687a0430c 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -24,9 +24,9 @@ #include "utilstrencodings.h" #include "validationinterface.h" -#include "governance-classes.h" -#include "masternode-payments.h" -#include "masternode-sync.h" +#include "governance/governance-classes.h" +#include "masternode/masternode-payments.h" +#include "masternode/masternode-sync.h" #include "evo/deterministicmns.h" #include "evo/specialtx.h" diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 7810d4a6bb7d..40af212f2f08 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -21,7 +21,7 @@ #include "wallet/walletdb.h" #endif -#include "masternode-sync.h" +#include "masternode/masternode-sync.h" #include "spork.h" #include diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index e6dd0d4cd695..a44af1d84a0d 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -24,7 +24,7 @@ #include "txmempool.h" #include "uint256.h" #include "utilstrencodings.h" -#include "instantx.h" +#include "instantsend.h" #ifdef ENABLE_WALLET #include "wallet/rpcwallet.h" #include "wallet/wallet.h" diff --git a/src/test/governance_validators_tests.cpp b/src/test/governance_validators_tests.cpp index 1d2e0c8dd644..89216ec3b2a2 100644 --- a/src/test/governance_validators_tests.cpp +++ b/src/test/governance_validators_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014-2018 The Dash Core developers -#include "governance-validators.h" +#include "governance/governance-validators.h" #include "utilstrencodings.h" #include "data/proposals_valid.json.h" diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 78b49cbc7dd5..0053764eb850 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -8,7 +8,7 @@ #include "consensus/merkle.h" #include "consensus/validation.h" #include "validation.h" -#include "masternode-payments.h" +#include "masternode/masternode-payments.h" #include "miner.h" #include "policy/policy.h" #include "pubkey.h" diff --git a/src/test/ratecheck_tests.cpp b/src/test/ratecheck_tests.cpp index cb9943eae2cc..e3d96b031144 100644 --- a/src/test/ratecheck_tests.cpp +++ b/src/test/ratecheck_tests.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2014-2018 The Dash Core developers -#include "governance.h" +#include "governance/governance.h" #include "test/test_dash.h" diff --git a/src/txmempool.cpp b/src/txmempool.cpp index a14ce6aab1e6..4cfcc21d3b14 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -8,7 +8,7 @@ #include "clientversion.h" #include "consensus/consensus.h" #include "consensus/validation.h" -#include "instantx.h" +#include "instantsend.h" #include "validation.h" #include "policy/policy.h" #include "policy/fees.h" diff --git a/src/validation.cpp b/src/validation.cpp index f4095e2ec4e3..6bb4681fb309 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -38,8 +38,8 @@ #include "versionbits.h" #include "warnings.h" -#include "instantx.h" -#include "masternode-payments.h" +#include "instantsend.h" +#include "masternode/masternode-payments.h" #include "evo/specialtx.h" #include "evo/providertx.h" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4eb4cc19aa9d..360b1d722689 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -10,7 +10,7 @@ #include "consensus/validation.h" #include "core_io.h" #include "init.h" -#include "instantx.h" +#include "instantsend.h" #include "net.h" #include "rpc/server.h" #include "timedata.h" @@ -20,7 +20,7 @@ #include "wallet.h" #include "walletdb.h" #include "keepass.h" -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #include "llmq/quorums_chainlocks.h" #include "llmq/quorums_instantsend.h" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f7892af93733..193ade4002de 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -28,10 +28,10 @@ #include "ui_interface.h" #include "utilmoneystr.h" -#include "governance.h" -#include "instantx.h" +#include "governance/governance.h" +#include "instantsend.h" #include "keepass.h" -#include "privatesend-client.h" +#include "privatesend/privatesend-client.h" #include "spork.h" #include "evo/providertx.h" diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 26095893b95f..72b7ff86c6fd 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -20,7 +20,7 @@ #include "wallet/walletdb.h" #include "wallet/rpcwallet.h" -#include "privatesend.h" +#include "privatesend/privatesend.h" #include #include diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h index c1a8e6c3f651..c90dc9db8e57 100644 --- a/src/zmq/zmqconfig.h +++ b/src/zmq/zmqconfig.h @@ -19,10 +19,10 @@ #include "primitives/block.h" #include "primitives/transaction.h" -#include "governance-object.h" -#include "governance-vote.h" +#include "governance/governance-object.h" +#include "governance/governance-vote.h" -#include "instantx.h" +#include "instantsend.h" void zmqError(const char *str); From a6eee07f29cce08e86d5817013123176295cbf24 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Tue, 21 May 2019 08:32:33 -0500 Subject: [PATCH 053/987] Merge bitcoin#9963: util: Properly handle errors during log message formatting (#2917) * Merge #9963: util: Properly handle errors during log message formatting b651270 util: Throw tinyformat::format_error on formatting error (Wladimir J. van der Laan) 3b092bd util: Properly handle errors during log message formatting (Wladimir J. van der Laan) Tree-SHA512: 85e3b7afec2255fc88034187f1abd6060e9421de17ed4e3d918416f393429a99cc2c974b362099aaaff6970549df47664bea4c857c4e46acc0789663201dc541 * "cast" debugMsg to a c string Signed-off-by: Pasta "cast" debugMsg to a c string pt 2 Signed-off-by: Pasta --- src/llmq/quorums.cpp | 2 +- src/llmq/quorums_dkgsessionhandler.cpp | 2 +- src/tinyformat.h | 9 ++++++++- src/util.h | 20 +++++++++++++++----- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 807db05df2dc..e34d81633494 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -212,7 +212,7 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToString(false)); } } - LogPrint("llmq", debugMsg); + LogPrint("llmq", debugMsg.c_str()); } g_connman->AddMasternodeQuorumNodes(llmqType, quorum->qc.quorumHash, connections); } diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index b00904ab4559..d76a6ecff652 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -489,7 +489,7 @@ void CDKGSessionHandler::HandleDKGRound() debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToString(false)); } } - LogPrint("llmq-dkg", debugMsg); + LogPrint("llmq-dkg", debugMsg.c_str()); } g_connman->AddMasternodeQuorumNodes(params.type, curQuorumHash, connections); } diff --git a/src/tinyformat.h b/src/tinyformat.h index db7641302e9d..10d73c2a0b90 100644 --- a/src/tinyformat.h +++ b/src/tinyformat.h @@ -123,7 +123,7 @@ namespace tinyformat {} namespace tfm = tinyformat; // Error handling; calls assert() by default. -#define TINYFORMAT_ERROR(reasonString) throw std::runtime_error(reasonString) +#define TINYFORMAT_ERROR(reasonString) throw tinyformat::format_error(reasonString) // Define for C++11 variadic templates which make the code shorter & more // general. If you don't define this, C++11 support is autodetected below. @@ -164,6 +164,13 @@ namespace tfm = tinyformat; namespace tinyformat { +class format_error: public std::runtime_error +{ +public: + format_error(const std::string &what): std::runtime_error(what) { + } +}; + //------------------------------------------------------------------------------ namespace detail { diff --git a/src/util.h b/src/util.h index aa303761d9de..3dfaa67155c6 100644 --- a/src/util.h +++ b/src/util.h @@ -110,14 +110,24 @@ std::string SafeStringFormat(const std::string& fmt, const Args&... args) } } -#define LogPrint(category, ...) do { \ - if (LogAcceptCategory((category))) { \ - LogPrintStr(SafeStringFormat(__VA_ARGS__)); \ +/** Get format string from VA_ARGS for error reporting */ +template std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; } + +#define LogPrintf(...) do { \ + std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \ + try { \ + _log_msg_ = tfm::format(__VA_ARGS__); \ + } catch (tinyformat::format_error &e) { \ + /* Original format string will have newline so don't add one here */ \ + _log_msg_ = "Error \"" + std::string(e.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \ } \ + LogPrintStr(_log_msg_); \ } while(0) -#define LogPrintf(...) do { \ - LogPrintStr(SafeStringFormat(__VA_ARGS__)); \ +#define LogPrint(category, ...) do { \ + if (LogAcceptCategory((category))) { \ + LogPrintf(__VA_ARGS__); \ + } \ } while(0) template From a3f03060973e199935cb19fec26098f7e34306a5 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 21 May 2019 16:36:13 +0300 Subject: [PATCH 054/987] Implement getmerkleblocks rpc (#2894) --- src/rpc/blockchain.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++ src/rpc/client.cpp | 1 + 2 files changed, 82 insertions(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e303f1393178..2d8eddadc6a6 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -837,6 +837,86 @@ UniValue getblockheaders(const JSONRPCRequest& request) return arrHeaders; } +UniValue getmerkleblocks(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) + throw std::runtime_error( + "getmerkleblocks \"filter\" \"hash\" ( count )\n" + "\nReturns an array of items with information about merkleblocks starting from which match .\n" + "\nArguments:\n" + "1. \"filter\" (string, required) The hex encoded bloom filter\n" + "2. \"hash\" (string, required) The block hash\n" + "3. count (numeric, optional, default/max=" + strprintf("%s", MAX_HEADERS_RESULTS) +")\n" + "\nResult (for verbose=false):\n" + "[\n" + " \"data\", (string) A string that is serialized, hex-encoded data for a merkleblock.\n" + " ...\n" + "]\n" + "\nExamples:\n" + + HelpExampleCli("getmerkleblocks", "\"2303028005802040100040000008008400048141010000f8400420800080025004000004130000000000000001\" \"00000000007e1432d2af52e8463278bf556b55cf5049262f25634557e2e91202\" 2000") + + HelpExampleRpc("getmerkleblocks", "\"2303028005802040100040000008008400048141010000f8400420800080025004000004130000000000000001\" \"00000000007e1432d2af52e8463278bf556b55cf5049262f25634557e2e91202\" 2000") + ); + + LOCK(cs_main); + + CBloomFilter filter; + std::string strFilter = request.params[0].get_str(); + CDataStream ssBloomFilter(ParseHex(strFilter), SER_NETWORK, PROTOCOL_VERSION); + ssBloomFilter >> filter; + if (!filter.IsWithinSizeConstraints()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Filter is not within size constraints"); + } + filter.UpdateEmptyFull(); + + std::string strHash = request.params[1].get_str(); + uint256 hash(uint256S(strHash)); + + if (mapBlockIndex.count(hash) == 0) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + } + + int nCount = MAX_HEADERS_RESULTS; + if (request.params.size() > 2) + nCount = request.params[2].get_int(); + + if (nCount <= 0 || nCount > (int)MAX_HEADERS_RESULTS) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Count is out of range"); + } + + CBlock block; + CBlockIndex* pblockindex = mapBlockIndex[hash]; + + if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0) { + throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)"); + } + + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) { + // Block not found on disk. This could be because we have the block + // header in our index but don't have the block (for example if a + // non-whitelisted node sends us an unrequested long chain of valid + // blocks, we add the headers to our index, but don't accept the + // block). + throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk"); + } + + UniValue arrMerkleBlocks(UniValue::VARR); + + for (; pblockindex; pblockindex = chainActive.Next(pblockindex)) + { + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) { + // this shouldn't happen, we already checked pruning case earlier + throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk"); + } + CDataStream ssMerkleBlock(SER_NETWORK, PROTOCOL_VERSION); + ssMerkleBlock << CMerkleBlock(block, filter); + std::string strHex = HexStr(ssMerkleBlock); + arrMerkleBlocks.push_back(strHex); + if (--nCount <= 0) + break; + } + return arrMerkleBlocks; +} + UniValue getblock(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) @@ -1760,6 +1840,7 @@ static const CRPCCommand commands[] = { "blockchain", "getblockhash", &getblockhash, true, {"height"} }, { "blockchain", "getblockheader", &getblockheader, true, {"blockhash","verbose"} }, { "blockchain", "getblockheaders", &getblockheaders, true, {"blockhash","count","verbose"} }, + { "blockchain", "getmerkleblocks", &getmerkleblocks, true, {"filter","blockhash","count"} }, { "blockchain", "getchaintips", &getchaintips, true, {"count","branchlen"} }, { "blockchain", "getdifficulty", &getdifficulty, true, {} }, { "blockchain", "getmempoolancestors", &getmempoolancestors, true, {"txid","verbose"} }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index a0572f867dfb..cc04555e469b 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -103,6 +103,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getblockheader", 1, "verbose" }, { "getblockheaders", 1, "count" }, { "getblockheaders", 2, "verbose" }, + { "getmerkleblocks", 2, "count" }, { "gettransaction", 1, "include_watchonly" }, { "getrawtransaction", 1, "verbose" }, { "createrawtransaction", 0, "inputs" }, From 2c833eff3e5229570227b43a7d13158ed99ce47a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 21 Mar 2017 11:46:44 +0100 Subject: [PATCH 055/987] Merge #10039: Fix compile errors with Qt 5.3.2 and Boost 1.55.0 b5bec4e Avoid QTimer::singleShot compile error with Qt 5.3.2 (Russell Yanofsky) d5046e7 Avoid scoped_connection compile error with boost 1.55.0 (Russell Yanofsky) Tree-SHA512: 96362b872817681b062e05c8fcb76cfc23b6e87e0371584a6aae0e17535fd34ccdba922380aa4b669a8e75ef3f9fadd25061541f77cb3198173f04249a7bcd62 --- src/qt/test/wallettests.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 5851175860da..4d7767de8c1a 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -22,7 +22,9 @@ namespace //! Press "Yes" button in modal send confirmation dialog. void ConfirmSend() { - QTimer::singleShot(0, Qt::PreciseTimer, []() { + QTimer* timer = new QTimer; + timer->setSingleShot(true); + QObject::connect(timer, &QTimer::timeout, []() { for (QWidget* widget : QApplication::topLevelWidgets()) { if (widget->inherits("SendConfirmationDialog")) { SendConfirmationDialog* dialog = qobject_cast(widget); @@ -32,6 +34,7 @@ void ConfirmSend() } } }); + timer->start(0); } //! Send coins to address and return txid. @@ -42,9 +45,9 @@ uint256 SendCoins(CWallet& wallet, SendCoinsDialog& sendCoinsDialog, const CBitc entry->findChild("payTo")->setText(QString::fromStdString(address.ToString())); entry->findChild("payAmount")->setValue(amount); uint256 txid; - boost::signals2::scoped_connection c = wallet.NotifyTransactionChanged.connect([&txid](CWallet*, const uint256& hash, ChangeType status) { + boost::signals2::scoped_connection c(wallet.NotifyTransactionChanged.connect([&txid](CWallet*, const uint256& hash, ChangeType status) { if (status == CT_NEW) txid = hash; - }); + })); ConfirmSend(); QMetaObject::invokeMethod(&sendCoinsDialog, "on_sendButton_clicked"); return txid; From f2e976a05129275e82d9a4ebd151e9ae1c825606 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 22 Mar 2017 08:37:58 +0100 Subject: [PATCH 056/987] Merge #10045: [trivial] Fix typos in comments dbf30ff [trivial] Fix typos in comments (practicalswift) Tree-SHA512: a841c96ba1a80ab57206e8ef4fa9b40ecff2244075a5539fc09f57e763bf2e92b0ed089e32a0dbac3902518dcda43d224f75a3462a560148841746560640ba70 --- src/base58.cpp | 2 +- src/bench/bench.h | 2 +- src/blockencodings.cpp | 2 +- src/qt/guiutil.cpp | 2 +- src/qt/test/paymentservertests.cpp | 2 +- src/test/addrman_tests.cpp | 2 +- src/test/checkqueue_tests.cpp | 2 +- src/test/cuckoocache_tests.cpp | 2 +- src/test/merkle_tests.cpp | 2 +- src/test/rpc_tests.cpp | 2 +- src/test/util_tests.cpp | 2 +- src/validation.cpp | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/base58.cpp b/src/base58.cpp index b24da81e236b..b251a688a3b8 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -134,7 +134,7 @@ bool DecodeBase58Check(const char* psz, std::vector& vchRet) vchRet.clear(); return false; } - // re-calculate the checksum, insure it matches the included 4-byte checksum + // re-calculate the checksum, ensure it matches the included 4-byte checksum uint256 hash = Hash(vchRet.begin(), vchRet.end() - 4); if (memcmp(&hash, &vchRet.end()[-4], 4) != 0) { vchRet.clear(); diff --git a/src/bench/bench.h b/src/bench/bench.h index 41d70d026124..5a050a746aa7 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -14,7 +14,7 @@ // Simple micro-benchmarking framework; API mostly matches a subset of the Google Benchmark // framework (see https://github.com/google/benchmark) -// Wny not use the Google Benchmark framework? Because adding Yet Another Dependency +// Why not use the Google Benchmark framework? Because adding Yet Another Dependency // (that uses cmake as its build system and has lots of features we don't need) isn't // worth it. diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 2c9d4f23df39..da4ce1392de7 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -147,7 +147,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c // request it. // This should be rare enough that the extra bandwidth doesn't matter, // but eating a round-trip due to FillBlock failure would be annoying - // Note that we dont want duplication between extra_txn and mempool to + // Note that we don't want duplication between extra_txn and mempool to // trigger this case, so we compare hashes first if (txn_available[idit->second] && txn_available[idit->second]->GetHash() != extra_txn[i].second->GetHash()) { diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index ca85d3e98a82..422c0a76c970 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -478,7 +478,7 @@ void SubstituteFonts(const QString& language) /* 10.10 or later system */ if (language == "zh_CN" || language == "zh_TW" || language == "zh_HK") // traditional or simplified Chinese QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Heiti SC"); - else if (language == "ja") // Japanesee + else if (language == "ja") // Japanese QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Songti SC"); else QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Lucida Grande"); diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index 84ccfea73007..08a76c7d4963 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -142,7 +142,7 @@ void PaymentServerTests::paymentServerTests() byteArray = QByteArray((const char*)&data[0], data.size()); r.paymentRequest.parse(byteArray); // Ensure the request is initialized, because network "main" is default, even for - // uninizialized payment requests and that will fail our test here. + // uninitialized payment requests and that will fail our test here. QVERIFY(r.paymentRequest.IsInitialized()); QCOMPARE(PaymentServer::verifyNetwork(r.paymentRequest.getDetails()), false); diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 7a35ff6da127..51effc24832e 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -413,7 +413,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) size_t percent23 = (addrman.size() * 23) / 100; BOOST_CHECK(vAddr.size() == percent23); BOOST_CHECK(vAddr.size() == 461); - // (Addrman.size() < number of addresses added) due to address collisons. + // (Addrman.size() < number of addresses added) due to address collisions. BOOST_CHECK(addrman.size() == 2007); } diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index cac968212e3e..72e4d3b37888 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -303,7 +303,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) } -// Test that blocks which might allocate lots of memory free their memory agressively. +// Test that blocks which might allocate lots of memory free their memory aggressively. // // This test attempts to catch a pathological case where by lazily freeing // checks might mean leaving a check un-swapped out, and decreasing by 1 each diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 228b3e571ae2..56bb7ed009dd 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -379,7 +379,7 @@ void test_cache_generations() // Loose Check that hit rate is above min_hit_rate BOOST_CHECK(hit > min_hit_rate); // Tighter check, count number of times we are less than tight_hit_rate - // (and implicityly, greater than min_hit_rate) + // (and implicitly, greater than min_hit_rate) out_of_tight_tolerance += hit < tight_hit_rate; } // Check that being out of tolerance happens less than diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index f779bd51e2e8..6a19de5d82ad 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) // If no mutation was done (once for every ntx value), try up to 16 branches. if (mutate == 0) { for (int loop = 0; loop < std::min(ntx, 16); loop++) { - // If ntx <= 16, try all branches. Otherise, try 16 random ones. + // If ntx <= 16, try all branches. Otherwise, try 16 random ones. int mtx = loop; if (ntx > 16) { mtx = insecure_rand() % ntx; diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 1ff02258ec07..af2f0812a64d 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -276,7 +276,7 @@ BOOST_AUTO_TEST_CASE(rpc_ban) BOOST_CHECK(banned_until.get_int64() > now); BOOST_CHECK(banned_until.get_int64()-now <= 200); - // must throw an exception because 127.0.0.1 is in already banned suubnet range + // must throw an exception because 127.0.0.1 is in already banned subnet range BOOST_CHECK_THROW(r = CallRPC(std::string("setban 127.0.0.1 add")), std::runtime_error); BOOST_CHECK_NO_THROW(CallRPC(std::string("setban 127.0.0.0/24 remove"))); diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index c08d082548e8..910a17554ba3 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -247,7 +247,7 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) for (int mod=2;mod<11;mod++) { int mask = 1; - // Really rough binomal confidence approximation. + // Really rough binomial confidence approximation. int err = 30*10000./mod*sqrt((1./mod*(1-1./mod))/10000.); //mask is 2^ceil(log2(mod))-1 while(mask& pblock, CValidation bool fTooFarAhead = (pindex->nHeight > int(chainActive.Height() + MIN_BLOCKS_TO_KEEP)); // TODO: Decouple this function from the block download logic by removing fRequested - // This requires some new chain datastructure to efficiently look up if a + // This requires some new chain data structure to efficiently look up if a // block is in a chain leading to a candidate for best tip, despite not // being such a candidate itself. From 7edb9e15ac3b69a9259a6c29e416b4a928234ffd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Mar 2017 13:03:26 +0100 Subject: [PATCH 057/987] Merge #10017: combine_logs.py - aggregates log files from multiple bitcoinds during functional tests. 8317a45 Python functional tests should log in UTC (John Newbery) 61d75f5 Introduce combine_logs.py to combine log files from multiple bitcoinds. (John Newbery) Tree-SHA512: 472a00907c938cd558353086eda0fbd8746a889680d5db4900eb95496f5f6a12eeb46560a5efd4bbfee10c85307fcf50d021356c5aad64168eb5cc2ababb073a --- test/functional/combine_logs.py | 111 ++++++++++++++++++ test/functional/combined_log_template.html | 40 +++++++ .../test_framework/test_framework.py | 2 + 3 files changed, 153 insertions(+) create mode 100755 test/functional/combine_logs.py create mode 100644 test/functional/combined_log_template.html diff --git a/test/functional/combine_logs.py b/test/functional/combine_logs.py new file mode 100755 index 000000000000..0c2f60172fa1 --- /dev/null +++ b/test/functional/combine_logs.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Combine logs from multiple bitcoin nodes as well as the test_framework log. + +This streams the combined log output to stdout. Use combine_logs.py > outputfile +to write to an outputfile.""" + +import argparse +from collections import defaultdict, namedtuple +import glob +import heapq +import os +import re +import sys + +# Matches on the date format at the start of the log event +TIMESTAMP_PATTERN = re.compile(r"^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{6}") + +LogEvent = namedtuple('LogEvent', ['timestamp', 'source', 'event']) + +def main(): + """Main function. Parses args, reads the log files and renders them as text or html.""" + + parser = argparse.ArgumentParser(usage='%(prog)s [options] ', description=__doc__) + parser.add_argument('-c', '--color', dest='color', action='store_true', help='outputs the combined log with events colored by source (requires posix terminal colors. Use less -r for viewing)') + parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. Requires jinja2. pip install jinja2') + args, unknown_args = parser.parse_known_args() + + if args.color and os.name != 'posix': + print("Color output requires posix terminal colors.") + sys.exit(1) + + if args.html and args.color: + print("Only one out of --color or --html should be specified") + sys.exit(1) + + # There should only be one unknown argument - the path of the temporary test directory + if len(unknown_args) != 1: + print("Unexpected arguments" + str(unknown_args)) + sys.exit(1) + + log_events = read_logs(unknown_args[0]) + + print_logs(log_events, color=args.color, html=args.html) + +def read_logs(tmp_dir): + """Reads log files. + + Delegates to generator function get_log_events() to provide individual log events + for each of the input log files.""" + + files = [("test", "%s/test_framework.log" % tmp_dir)] + for i, logfile in enumerate(glob.glob("%s/node*/regtest/debug.log" % tmp_dir)): + files.append(("node%d" % i, logfile)) + + return heapq.merge(*[get_log_events(source, f) for source, f in files]) + +def get_log_events(source, logfile): + """Generator function that returns individual log events. + + Log events may be split over multiple lines. We use the timestamp + regex match as the marker for a new log event.""" + try: + with open(logfile, 'r') as infile: + event = '' + timestamp = '' + for line in infile: + # skip blank lines + if line == '\n': + continue + # if this line has a timestamp, it's the start of a new log event. + time_match = TIMESTAMP_PATTERN.match(line) + if time_match: + if event: + yield LogEvent(timestamp=timestamp, source=source, event=event.rstrip()) + event = line + timestamp = time_match.group() + # if it doesn't have a timestamp, it's a continuation line of the previous log. + else: + event += "\n" + line + # Flush the final event + yield LogEvent(timestamp=timestamp, source=source, event=event.rstrip()) + except FileNotFoundError: + print("File %s could not be opened. Continuing without it." % logfile, file=sys.stderr) + +def print_logs(log_events, color=False, html=False): + """Renders the iterator of log events into text or html.""" + if not html: + colors = defaultdict(lambda: '') + if color: + colors["test"] = "\033[0;36m" # CYAN + colors["node0"] = "\033[0;34m" # BLUE + colors["node1"] = "\033[0;32m" # GREEN + colors["node2"] = "\033[0;31m" # RED + colors["node3"] = "\033[0;33m" # YELLOW + colors["reset"] = "\033[0m" # Reset font color + + for event in log_events: + print("{0} {1: <5} {2} {3}".format(colors[event.source.rstrip()], event.source, event.event, colors["reset"])) + + else: + try: + import jinja2 + except ImportError: + print("jinja2 not found. Try `pip install jinja2`") + sys.exit(1) + print(jinja2.Environment(loader=jinja2.FileSystemLoader('./')) + .get_template('combined_log_template.html') + .render(title="Combined Logs from testcase", log_events=[event._asdict() for event in log_events])) + +if __name__ == '__main__': + main() diff --git a/test/functional/combined_log_template.html b/test/functional/combined_log_template.html new file mode 100644 index 000000000000..c0b854b08056 --- /dev/null +++ b/test/functional/combined_log_template.html @@ -0,0 +1,40 @@ + + + {{ title }} + + + +
    +{% for event in log_events %} +
  • {{ event.source }} {{ event.timestamp }} {{event.event}}
  • +{% endfor %} +
+ + diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 9b0d6a275e18..8b8c4c237974 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -10,6 +10,7 @@ import sys import shutil import tempfile +import time import traceback from concurrent.futures import ThreadPoolExecutor from time import time, sleep @@ -222,6 +223,7 @@ def _start_logging(self): ch.setLevel(ll) # Format logs the same as bitcoind's debug.log with microprecision (so log files can be concatenated and sorted) formatter = logging.Formatter(fmt = '%(asctime)s.%(msecs)03d000 %(name)s (%(levelname)s): %(message)s', datefmt='%Y-%m-%d %H:%M:%S') + formatter.converter = time.gmtime fh.setFormatter(formatter) ch.setFormatter(formatter) # add the handlers to the logger From 2aa3f890d1efa60fd49f9443274c4fa3ab2a0bee Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 23 Mar 2017 08:16:14 +0100 Subject: [PATCH 058/987] Merge #10029: Fix parameter naming inconsistencies between .h and .cpp files 97b8213 Fix parameter naming inconsistencies between .h and .cpp files (practicalswift) Tree-SHA512: 4f46cc3973a898d2478bdb1b8c8d1829c3a7298b63bc47359c5dc2f135466773072d9672134ef3e7557dfc913720e49b675176b9e435b8bd1992af9ad53866e4 --- src/rpc/server.h | 2 +- src/txmempool.cpp | 2 +- src/txmempool.h | 8 ++++---- src/validation.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rpc/server.h b/src/rpc/server.h index 10d4a94f4d34..1cbcf2e21166 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -66,7 +66,7 @@ void SetRPCWarmupStatus(const std::string& newStatus); void SetRPCWarmupFinished(); /* returns the current warmup state. */ -bool RPCIsInWarmup(std::string *statusOut); +bool RPCIsInWarmup(std::string *outStatus); /** * Type-check arguments; throws JSONRPCError if wrong type given. Does not check that diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 4cfcc21d3b14..de9c9bdb3af8 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -111,7 +111,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan // vHashesToUpdate is the set of transaction hashes from a disconnected block // which has been re-added to the mempool. -// for each entry, look for descendants that are outside hashesToUpdate, and +// for each entry, look for descendants that are outside vHashesToUpdate, and // add fee/size information for such descendants to the parent. // for each such descendant, also update the ancestor state to include the parent. void CTxMemPool::UpdateTransactionsFromBlock(const std::vector &vHashesToUpdate) diff --git a/src/txmempool.h b/src/txmempool.h index bceffd19542a..3efd357570b0 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -604,12 +604,12 @@ class CTxMemPool * new mempool entries may have children in the mempool (which is generally * not the case when otherwise adding transactions). * UpdateTransactionsFromBlock() will find child transactions and update the - * descendant state for each transaction in hashesToUpdate (excluding any - * child transactions present in hashesToUpdate, which are already accounted - * for). Note: hashesToUpdate should be the set of transactions from the + * descendant state for each transaction in vHashesToUpdate (excluding any + * child transactions present in vHashesToUpdate, which are already accounted + * for). Note: vHashesToUpdate should be the set of transactions from the * disconnected block that have been accepted back into the mempool. */ - void UpdateTransactionsFromBlock(const std::vector &hashesToUpdate); + void UpdateTransactionsFromBlock(const std::vector &vHashesToUpdate); /** Try to calculate all in-mempool ancestors of entry. * (these are all calculated including the tx itself) diff --git a/src/validation.h b/src/validation.h index 6be85f4ae6a3..3f7aca5fc806 100644 --- a/src/validation.h +++ b/src/validation.h @@ -327,7 +327,7 @@ void FlushStateToDisk(); /** Prune block files and flush state to disk. */ void PruneAndFlush(); /** Prune block files up to a given height */ -void PruneBlockFilesManual(int nPruneUpToHeight); +void PruneBlockFilesManual(int nManualPruneHeight); /** (try to) add transaction to memory pool */ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, From 07e0567dcc2c257d5a2ca58015f1032a5f7f1dc9 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 23 Mar 2017 08:18:35 +0100 Subject: [PATCH 059/987] Merge #9558: Clarify assumptions made about when BlockCheck is called c4a6929 Clarify assumptions made about when BlockCheck is called (Matt Corallo) Tree-SHA512: 2eceb0c4f06c7fd6b290b93843bda11a4b63131559c5e8226bfec84596ed4e54ee6d8f5bc9cf789a80675be8b8079cf9234c96032df306258cb2260b9d8c7825 --- src/validationinterface.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/validationinterface.h b/src/validationinterface.h index f4ac971bad8e..c2abe404a0ce 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -96,7 +96,12 @@ struct CMainSignals { boost::signals2::signal Inventory; /** Tells listeners to broadcast their data. */ boost::signals2::signal Broadcast; - /** Notifies listeners of a block validation result */ + /** + * Notifies listeners of a block validation result. + * If the provided CValidationState IsValid, the provided block + * is guaranteed to be the current best block at the time the + * callback was generated (not necessarily now) + */ boost::signals2::signal BlockChecked; /** Notifies listeners that a key for mining is required (coinbase) */ boost::signals2::signal&)> ScriptForMining; From 96a5f5730bd13dbce72c2634297b2b68e4326921 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 23 Mar 2017 08:27:05 +0100 Subject: [PATCH 060/987] Merge #9500: [Qt][RPC] Autocomplete commands for 'help' command in debug console 6d8fe35 'help' rpc commands autocomplete (Andrew Chow) Tree-SHA512: 289bc4fa16a1c0291262998caa18556f1c5aa89662c85528606dc03b596b8833a0fb2c5c9c068b6dcf2adb3a136d4f154591d4a95b8c3313638b77355aaed955 --- src/qt/rpcconsole.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 01f5c4aeecf0..995582d6e464 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -658,9 +658,12 @@ void RPCConsole::setClientModel(ClientModel *model) for (size_t i = 0; i < commandList.size(); ++i) { wordList << commandList[i].c_str(); + wordList << ("help " + commandList[i]).c_str(); } + wordList.sort(); autoCompleter = new QCompleter(wordList, this); + autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel); ui->lineEdit->setCompleter(autoCompleter); autoCompleter->popup()->installEventFilter(this); // Start thread to execute RPC commands. From 9f07f489dea9dd0f7582cc34a7c2d3558fbb6d76 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 23 Mar 2017 11:36:45 +0100 Subject: [PATCH 061/987] Merge #10047: [tests] Remove unused variables and imports 3897459 [tests] Remove unused variables (practicalswift) 72163d4 [tests] Remove unused and duplicate imports (practicalswift) Tree-SHA512: 926af14b844bfca3bdd08b3cfdcb0edd3652efb4612d5571fee9abb917a6ce4e7d11d3601ff9c3d017e943ebe1e9ebdfccaf0af3db84d201b61941e9c1c9146a --- contrib/testgen/gen_base58_test_vectors.py | 2 +- test/functional/bip68-sequence.py | 4 ++-- test/functional/fundrawtransaction.py | 1 - test/functional/import-rescan.py | 1 - test/functional/multi_rpc.py | 2 -- test/functional/rawtransactions.py | 1 - test/functional/smartfees.py | 3 +-- test/functional/test_framework/socks5.py | 1 - test/functional/test_framework/test_framework.py | 1 - test/functional/zmq_test.py | 1 - 10 files changed, 4 insertions(+), 13 deletions(-) diff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py index ccdcfa5269c1..0146fffc6abe 100755 --- a/contrib/testgen/gen_base58_test_vectors.py +++ b/contrib/testgen/gen_base58_test_vectors.py @@ -13,7 +13,7 @@ # Released under MIT License import os from itertools import islice -from base58 import b58encode, b58decode, b58encode_chk, b58decode_chk, b58chars +from base58 import b58encode_chk, b58decode_chk, b58chars import random from binascii import b2a_hex diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py index 5a628a2fa0bf..408730f4919a 100755 --- a/test/functional/bip68-sequence.py +++ b/test/functional/bip68-sequence.py @@ -378,8 +378,8 @@ def activateCSV(self): # activation should happen at block height 432 (3 periods) min_activation_height = 432 height = self.nodes[0].getblockcount() - assert(height < 432) - self.nodes[0].generate(432-height) + assert(height < min_activation_height) + self.nodes[0].generate(min_activation_height-height) assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active') sync_blocks(self.nodes) diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index 18eb5d02baa6..8369bd5a831a 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -698,7 +698,6 @@ def run_test(self): inputs = [] outputs = {self.nodes[2].getnewaddress(): value for value in (1.0, 1.1, 1.2, 1.3)} - keys = list(outputs.keys()) rawtx = self.nodes[3].createrawtransaction(inputs, outputs) result = [self.nodes[3].fundrawtransaction(rawtx), diff --git a/test/functional/import-rescan.py b/test/functional/import-rescan.py index fb5e1d6c702b..659baa61c408 100755 --- a/test/functional/import-rescan.py +++ b/test/functional/import-rescan.py @@ -22,7 +22,6 @@ from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework from test_framework.util import (start_nodes, connect_nodes, sync_blocks, assert_equal, set_node_times) -from decimal import Decimal import collections import enum diff --git a/test/functional/multi_rpc.py b/test/functional/multi_rpc.py index a374d63f1059..1179b406fca8 100755 --- a/test/functional/multi_rpc.py +++ b/test/functional/multi_rpc.py @@ -41,11 +41,9 @@ def run_test(self): authpair = url.username + ':' + url.password #New authpair generated via share/rpcuser tool - rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" password = "cA773lm788buwYe4g4WT+05pKyNruVKjQ25x3n0DQcM=" #Second authpair with different username - rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" password2 = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI=" authpairnew = "rt:"+password diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py index 56cfa8ff4930..b798b73db78b 100755 --- a/test/functional/rawtransactions.py +++ b/test/functional/rawtransactions.py @@ -104,7 +104,6 @@ def run_test(self): txId = self.nodes[0].sendtoaddress(mSigObj, 2.2) decTx = self.nodes[0].gettransaction(txId) rawTx = self.nodes[0].decoderawtransaction(decTx['hex']) - sPK = rawTx['vout'][0]['scriptPubKey']['hex'] self.sync_all() self.nodes[0].generate(1) self.sync_all() diff --git a/test/functional/smartfees.py b/test/functional/smartfees.py index dae8f24f76ad..921178925f2c 100755 --- a/test/functional/smartfees.py +++ b/test/functional/smartfees.py @@ -4,11 +4,10 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test fee estimation code.""" -from collections import OrderedDict from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.script import CScript, OP_1, OP_DROP, OP_2, OP_HASH160, OP_EQUAL, hash160, OP_TRUE -from test_framework.mininode import CTransaction, CTxIn, CTxOut, COutPoint, ToHex, FromHex, COIN +from test_framework.mininode import CTransaction, CTxIn, CTxOut, COutPoint, ToHex, COIN # Construct 2 trivial P2SH's and the ScriptSigs that spend them # So we can create many many transactions without needing to spend diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py index dd7624d4540e..a08b03ed24df 100644 --- a/test/functional/test_framework/socks5.py +++ b/test/functional/test_framework/socks5.py @@ -5,7 +5,6 @@ """Dummy Socks5 server for testing.""" import socket, threading, queue -import traceback, sys import logging logger = logging.getLogger("TestFramework.socks5") diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 8b8c4c237974..9cac0547837e 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -11,7 +11,6 @@ import shutil import tempfile import time -import traceback from concurrent.futures import ThreadPoolExecutor from time import time, sleep diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index e6f18b0b9332..9e27b46381dc 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -41,7 +41,6 @@ def run_test(self): topic = msg[0] assert_equal(topic, b"hashtx") body = msg[1] - nseq = msg[2] msgSequence = struct.unpack(' Date: Fri, 24 Mar 2017 13:57:36 +0100 Subject: [PATCH 062/987] Merge #10053: [test] Allow functional test cases to be skipped 0c1ade6 Skip rpcbind_test if OS/network requirements are not met. (John Newbery) 232b666 Allow test cases to be skipped (John Newbery) Tree-SHA512: d90c956ba6e27e53f422cba6267bdcc60faef9370a7e66b7f6480137f84d9a813442ac477b20fbbc540be2b4636928be910c46e221570ab3b9a5b9f0f11f7fc8 --- test/functional/rpcbind_test.py | 18 +++++++++++-- .../test_framework/test_framework.py | 9 ++++--- test/functional/test_runner.py | 26 ++++++++++++------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/test/functional/rpcbind_test.py b/test/functional/rpcbind_test.py index 8720a345cea5..efc36481d183 100755 --- a/test/functional/rpcbind_test.py +++ b/test/functional/rpcbind_test.py @@ -4,6 +4,9 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test running bitcoind with the -rpcbind and -rpcallowip options.""" +import socket +import sys + from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.netutil import * @@ -52,7 +55,9 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport): def run_test(self): # due to OS-specific network stats queries, this test works only on Linux - assert(sys.platform.startswith('linux')) + if not sys.platform.startswith('linux'): + self.log.warning("This test can only be run on linux. Skipping test.") + sys.exit(self.TEST_EXIT_SKIPPED) # find the first non-loopback interface for testing non_loopback_ip = None for name,ip in all_interfaces(): @@ -60,7 +65,16 @@ def run_test(self): non_loopback_ip = ip break if non_loopback_ip is None: - assert(not 'This test requires at least one non-loopback IPv4 interface') + self.log.warning("This test requires at least one non-loopback IPv4 interface. Skipping test.") + sys.exit(self.TEST_EXIT_SKIPPED) + try: + s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + s.connect(("::1",1)) + s.close + except OSError: + self.log.warning("This test requires IPv6 support. Skipping test.") + sys.exit(self.TEST_EXIT_SKIPPED) + self.log.info("Using interface %s for testing" % non_loopback_ip) defaultport = rpc_port(0) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 9cac0547837e..c955f5c3bd38 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -41,9 +41,12 @@ copy_datadir) from .authproxy import JSONRPCException - class BitcoinTestFramework(object): + TEST_EXIT_PASSED = 0 + TEST_EXIT_FAILED = 1 + TEST_EXIT_SKIPPED = 77 + def __init__(self): self.num_nodes = 4 self.setup_clean_chain = False @@ -202,11 +205,11 @@ def main(self): print("".join(deque(open(f), MAX_LINES_TO_PRINT))) if success: self.log.info("Tests successful") - sys.exit(0) + sys.exit(self.TEST_EXIT_PASSED) else: self.log.error("Test failed. Test logging available at %s/test_framework.log", self.options.tmpdir) logging.shutdown() - sys.exit(1) + sys.exit(self.TEST_EXIT_FAILED) def _start_logging(self): # Add logger and logging handlers diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 0a1ee9cebf17..db69aa280a47 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -24,6 +24,9 @@ import tempfile import re +TEST_EXIT_PASSED = 0 +TEST_EXIT_SKIPPED = 77 + BASE_SCRIPTS= [ # Scripts that are run by the travis build process. # Longest test should go first, to favor running tests in parallel @@ -258,20 +261,20 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal job_queue = TestHandler(jobs, tests_dir, test_list, flags) max_len_name = len(max(test_list, key=len)) - results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "PASSED", "DURATION") + BOLD[0] + results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] for _ in range(len(test_list)): - (name, stdout, stderr, passed, duration) = job_queue.get_next() - all_passed = all_passed and passed + (name, stdout, stderr, status, duration) = job_queue.get_next() + all_passed = all_passed and status != "Failed" time_sum += duration print('\n' + BOLD[1] + name + BOLD[0] + ":") - print('' if passed else stdout + '\n', end='') + print('' if status == "Passed" else stdout + '\n', end='') print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='') - print("Pass: %s%s%s, Duration: %s s\n" % (BOLD[1], passed, BOLD[0], duration)) + print("Status: %s%s%s, Duration: %s s\n" % (BOLD[1], status, BOLD[0], duration)) - results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration) + results += "%s | %s | %s s\n" % (name.ljust(max_len_name), status.ljust(7), duration) - results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(6), time_sum) + BOLD[0] + results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(7), time_sum) + BOLD[0] print(results) print("\nRuntime: %s s" % (int(time.time() - time0))) @@ -328,10 +331,15 @@ def get_next(self): log_out.seek(0), log_err.seek(0) [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] log_out.close(), log_err.close() - passed = stderr == "" and proc.returncode == 0 + if proc.returncode == TEST_EXIT_PASSED and stderr == "": + status = "Passed" + elif proc.returncode == TEST_EXIT_SKIPPED: + status = "Skipped" + else: + status = "Failed" self.num_running -= 1 self.jobs.remove(j) - return name, stdout, stderr, passed, int(time.time() - time0) + return name, stdout, stderr, status, int(time.time() - time0) print('.', end='', flush=True) From ba20c9031d0dbbb3704b5293a2695879d503481b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 25 Mar 2017 09:09:58 +0100 Subject: [PATCH 063/987] Merge #10067: [trivial] Dead code removal c59aedc [trivial] Dead code removal (Thomas Snider) Tree-SHA512: 09962c1ae36fb2f19b7e4a03abf3de6632bab984ce30040ca3f843431df33a0f8fa6a2c1d55b076b800547bb656e344d74ea085ff081b613bcdfd7d2f9826374 --- src/miner.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index dd039148368a..68a32ad9e004 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -37,8 +37,6 @@ #include "llmq/quorums_chainlocks.h" #include -#include -#include #include #include @@ -56,17 +54,6 @@ uint64_t nLastBlockTx = 0; uint64_t nLastBlockSize = 0; -class ScoreCompare -{ -public: - ScoreCompare() {} - - bool operator()(const CTxMemPool::txiter a, const CTxMemPool::txiter b) - { - return CompareTxMemPoolEntryByScore()(*b,*a); // Convert to less than - } -}; - int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { int64_t nOldTime = pblock->nTime; From 37931293158b2bd19567b5f6079d045bd934bb02 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 25 Mar 2017 12:15:01 +0100 Subject: [PATCH 064/987] Merge #9946: Fix build errors if spaces in path or parent directory b1f584d fix build if spaces in src dir path (Matthew Zipkin) Tree-SHA512: 5834690c1f63b85ed04bb8ed411a94da04738534364d58bd9ee333ccff7129b2bbb710f31598c40123199e023da02c1745514294af3efdbb2c2e4c1320aded35 --- src/Makefile.am | 4 ++-- test/functional/test_runner.py | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7aa6a2fbd254..bfa5b04f36e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -250,8 +250,8 @@ BITCOIN_CORE_H = \ obj/build.h: FORCE @$(MKDIR_P) $(builddir)/obj - @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \ - $(abs_top_srcdir) + @$(top_srcdir)/share/genbuild.sh "$(abs_top_builddir)/src/obj/build.h" \ + "$(abs_top_srcdir)" libdash_util_a-clientversion.$(OBJEXT): obj/build.h # server: shared between dashd and dash-qt diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index db69aa280a47..0bd9d4afb47e 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -105,7 +105,7 @@ ZMQ_SCRIPTS = [ # ZMQ test can only be run if Dash Core was built with zmq-enabled. # call test_runner.py with -nozmq to explicitly exclude these tests. - "zmq_test.py"] + 'zmq_test.py'] EXTENDED_SCRIPTS = [ # These tests are not run by the travis build process. @@ -219,9 +219,9 @@ def main(): sys.exit(0) if args.help: - # Print help for test_runner.py, then print help of the first script and exit. + # Print help for test_runner.py, then print help of the first script (with args removed) and exit. parser.print_help() - subprocess.check_call((config["environment"]["SRCDIR"] + '/test/functional/' + test_list[0]).split() + ['-h']) + subprocess.check_call([(config["environment"]["SRCDIR"] + '/test/functional/' + test_list[0].split()[0])] + ['-h']) sys.exit(0) run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args) @@ -312,9 +312,10 @@ def get_next(self): port_seed = ["--portseed={}".format(len(self.test_list) + self.portseed_offset)] log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) + test_argv = t.split() self.jobs.append((t, time.time(), - subprocess.Popen((self.tests_dir + t).split() + self.flags + port_seed, + subprocess.Popen([self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + port_seed, universal_newlines=True, stdout=log_stdout, stderr=log_stderr), From 1781c7a701b8cd71aef32f87c9c70452d9ba55fe Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 25 Mar 2017 16:10:44 +0100 Subject: [PATCH 065/987] Merge #10069: [QA] Fix typo in fundrawtransaction test 803e6a3 [QA] Fix typo in fundrawtransaction test (Nicolas Dorier) Tree-SHA512: 7b88cf09d7e756f0f5535738993868287d4c7049db44072e318f48a9b08786bebb9877f787471bbf6aac58b3d709275eefa372d727f4afd6ded41494fe0024d1 --- test/functional/fundrawtransaction.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index 8369bd5a831a..e049e5ab7f14 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -477,7 +477,7 @@ def run_test(self): rawTx = self.nodes[1].createrawtransaction(inputs, outputs) # fund a transaction that requires a new key for the change output # creating the key must be impossible because the wallet is locked - assert_raises_jsonrpc(-4, "Insufficient funds", self.nodes[1].fundrawtransaction, rawtx) + assert_raises_jsonrpc(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawTx) #refill the keypool self.nodes[1].walletpassphrase("test", 100) From 12094179388665348f621ec4b8cfb26bc7511cbe Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Mar 2017 09:10:37 +0200 Subject: [PATCH 066/987] Merge #10083: [QA] Renaming rawTx into rawtx dd5be2c [QA] Renaming rawTx into rawtx (NicolasDorier) Tree-SHA512: c999c3cbe7bbd00bf5cc9813741c485caea9925de1214c8a7ef717a7c109c1a8baf73b460db3b08f4ec138d773b46176531c48295504ed75180d4b3666b85b99 --- test/functional/fundrawtransaction.py | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index e049e5ab7f14..e5c145f3c30f 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -327,8 +327,8 @@ def run_test(self): #compare fee of a standard pubkeyhash transaction inputs = [] outputs = {self.nodes[1].getnewaddress():11} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[0].fundrawtransaction(rawTx) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 11) @@ -343,8 +343,8 @@ def run_test(self): #compare fee of a standard pubkeyhash transaction with multiple outputs inputs = [] outputs = {self.nodes[1].getnewaddress():11,self.nodes[1].getnewaddress():12,self.nodes[1].getnewaddress():1,self.nodes[1].getnewaddress():13,self.nodes[1].getnewaddress():2,self.nodes[1].getnewaddress():3} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[0].fundrawtransaction(rawTx) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[0].sendmany("", outputs) signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] @@ -369,8 +369,8 @@ def run_test(self): inputs = [] outputs = {mSigObj:11} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[0].fundrawtransaction(rawTx) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(mSigObj, 11) @@ -402,8 +402,8 @@ def run_test(self): inputs = [] outputs = {mSigObj:11} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[0].fundrawtransaction(rawTx) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(mSigObj, 11) @@ -437,8 +437,8 @@ def run_test(self): oldBalance = self.nodes[1].getbalance() inputs = [] outputs = {self.nodes[1].getnewaddress():11} - rawTx = self.nodes[2].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[2].fundrawtransaction(rawTx) + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[2].fundrawtransaction(rawtx) signedTx = self.nodes[2].signrawtransaction(fundedTx['hex']) txId = self.nodes[2].sendrawtransaction(signedTx['hex']) @@ -474,10 +474,10 @@ def run_test(self): self.nodes[1].getnewaddress() inputs = [] outputs = {self.nodes[0].getnewaddress():1.1} - rawTx = self.nodes[1].createrawtransaction(inputs, outputs) + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) # fund a transaction that requires a new key for the change output # creating the key must be impossible because the wallet is locked - assert_raises_jsonrpc(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawTx) + assert_raises_jsonrpc(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawtx) #refill the keypool self.nodes[1].walletpassphrase("test", 100) @@ -489,8 +489,8 @@ def run_test(self): inputs = [] outputs = {self.nodes[0].getnewaddress():11} - rawTx = self.nodes[1].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[1].fundrawtransaction(rawTx) + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawtx) #now we need to unlock self.nodes[1].walletpassphrase("test", 600) @@ -520,8 +520,8 @@ def run_test(self): #fund a tx with ~20 small inputs inputs = [] outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} - rawTx = self.nodes[1].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[1].fundrawtransaction(rawTx) + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[1].sendmany("", outputs) @@ -552,8 +552,8 @@ def run_test(self): inputs = [] outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} - rawTx = self.nodes[1].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[1].fundrawtransaction(rawTx) + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawtx) fundedAndSignedTx = self.nodes[1].signrawtransaction(fundedTx['hex']) txId = self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex']) self.sync_all() From 14001a3d940b5e6e5e051c6cadb028a37598198e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Mar 2017 09:34:50 +0200 Subject: [PATCH 067/987] Merge #10085: Docs: remove 'noconnect' option d5690f1 remove 'noconnect' option from documentation (Jameson Lopp) Tree-SHA512: 9c61df5ee7b2b9a8188cbf44fced05c41ded3454758dbc1b1ae641cea0301a65169381f20c045027e571ebe211a42e680a66daed47090f91766403cc60147e89 --- src/init.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 1732b2eae051..aee139e6e517 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -473,13 +473,13 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-banscore=", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), DEFAULT_BANSCORE_THRESHOLD)); strUsage += HelpMessageOpt("-bantime=", strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), DEFAULT_MISBEHAVING_BANTIME)); strUsage += HelpMessageOpt("-bind=", _("Bind to given address and always listen on it. Use [host]:port notation for IPv6")); - strUsage += HelpMessageOpt("-connect=", _("Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections")); + strUsage += HelpMessageOpt("-connect=", _("Connect only to the specified node(s); -connect=0 disables automatic connections")); strUsage += HelpMessageOpt("-discover", _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)")); strUsage += HelpMessageOpt("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + strprintf(_("(default: %u)"), DEFAULT_NAME_LOOKUP)); - strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect)")); + strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)")); strUsage += HelpMessageOpt("-externalip=", _("Specify your own public address")); strUsage += HelpMessageOpt("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), DEFAULT_FORCEDNSSEED)); - strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect/-noconnect)")); + strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)")); strUsage += HelpMessageOpt("-listenonion", strprintf(_("Automatically create Tor hidden service (default: %d)"), DEFAULT_LISTEN_ONION)); strUsage += HelpMessageOpt("-maxconnections=", strprintf(_("Maintain at most connections to peers (temporary service connections excluded) (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); strUsage += HelpMessageOpt("-maxreceivebuffer=", strprintf(_("Maximum per-connection receive buffer, *1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER)); From 142b5cba0b2b258c142358c72819d5aabe86aa9c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Mar 2017 09:49:11 +0200 Subject: [PATCH 068/987] Merge #10073: Actually run assumevalid.py 717ad13 Actually run assumevalid.py. (John Newbery) Tree-SHA512: 6fd55789be43e26347f8f5456194aa5e7beeeba3db85411dc75581b98059ca3a85485494fca36848f21c0f48096004906a0409fd76309951b5f977bab9f45b91 --- test/functional/assumevalid.py | 102 +++++++++++++++++++-------------- test/functional/test_runner.py | 1 + 2 files changed, 59 insertions(+), 44 deletions(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index c60c8e6d1a91..da680a5d24ba 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -15,7 +15,7 @@ 2-101: bury that block with 100 blocks so the coinbase transaction output can be spent 102: a block containing a transaction spending the coinbase - transaction output. The transaction has an invalid signature. + transaction output. The transaction has an invalid signature. 103-2202: bury the bad block with just over two weeks' worth of blocks (2100 blocks) @@ -29,40 +29,34 @@ block 200. node2 will reject block 102 since it's assumed valid, but it isn't buried by at least two weeks' work. """ +import time -from test_framework.mininode import * -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from test_framework.blocktools import create_block, create_coinbase +from test_framework.blocktools import (create_block, create_coinbase) from test_framework.key import CECKey -from test_framework.script import * +from test_framework.mininode import (CBlockHeader, + COutPoint, + CTransaction, + CTxIn, + CTxOut, + NetworkThread, + NodeConn, + SingleNodeConnCB, + msg_block, + msg_headers) +from test_framework.script import (CScript, OP_TRUE) +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import (start_node, p2p_port, assert_equal) class BaseNode(SingleNodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) - self.last_inv = None - self.last_headers = None - self.last_block = None - self.last_getdata = None - self.block_announced = False - self.last_getheaders = None - self.disconnected = False - self.last_blockhash_announced = None - - def on_close(self, conn): - self.disconnected = True - - def wait_for_disconnect(self, timeout=60): - test_function = lambda: self.disconnected - assert(wait_until(test_function, timeout=timeout)) - return + super().__init__() def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() - headers_message.headers = [ CBlockHeader(b) for b in new_blocks ] + headers_message.headers = [CBlockHeader(b) for b in new_blocks] self.send_message(headers_message) -class SendHeadersTest(BitcoinTestFramework): +class AssumeValidTest(BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True @@ -72,8 +66,34 @@ def setup_network(self): # Start node0. We don't start the other nodes yet since # we need to pre-mine a block with an invalid transaction # signature so we can pass in the block hash as assumevalid. - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir)) + self.nodes = [start_node(0, self.options.tmpdir)] + + def send_blocks_until_disconnected(self, node): + """Keep sending blocks to the node until we're disconnected.""" + for i in range(len(self.blocks)): + try: + node.send_message(msg_block(self.blocks[i])) + except IOError as e: + assert str(e) == 'Not connected, no pushbuf' + break + + def assert_blockchain_height(self, node, height): + """Wait until the blockchain is no longer advancing and verify it's reached the expected height.""" + last_height = node.getblock(node.getbestblockhash())['height'] + timeout = 10 + while True: + time.sleep(0.25) + current_height = node.getblock(node.getbestblockhash())['height'] + if current_height != last_height: + last_height = current_height + if timeout < 0: + assert False, "blockchain too short after timeout: %d" % current_height + timeout - 0.25 + continue + elif current_height > height: + assert False, "blockchain too long: %d" % current_height + elif current_height == height: + break def run_test(self): @@ -83,7 +103,7 @@ def run_test(self): connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0)) node0.add_connection(connections[0]) - NetworkThread().start() # Start up network handling in another thread + NetworkThread().start() # Start up network handling in another thread node0.wait_for_verack() # Build the blockchain @@ -120,7 +140,7 @@ def run_test(self): # Create a transaction spending the coinbase output with an invalid (null) signature tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.block1.vtx[0].sha256, 0), scriptSig=b"")) - tx.vout.append(CTxOut(49*100000000, CScript([OP_TRUE]))) + tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE]))) tx.calc_sha256() block102 = create_block(self.tip, create_coinbase(height), self.block_time) @@ -166,25 +186,19 @@ def run_test(self): node1.send_header_for_blocks(self.blocks[2000:]) node2.send_header_for_blocks(self.blocks[0:200]) - # Send 102 blocks to node0. Block 102 will be rejected. - for i in range(101): - node0.send_message(msg_block(self.blocks[i])) - node0.sync_with_ping() # make sure the most recent block is synced - node0.send_message(msg_block(self.blocks[101])) - assert_equal(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['height'], 101) + # Send blocks to node0. Block 102 will be rejected. + self.send_blocks_until_disconnected(node0) + self.assert_blockchain_height(self.nodes[0], 101) - # Send 3102 blocks to node1. All blocks will be accepted. + # Send all blocks to node1. All blocks will be accepted. for i in range(2202): node1.send_message(msg_block(self.blocks[i])) - node1.sync_with_ping() # make sure the most recent block is synced + node1.sync_with_ping() # make sure the most recent block is synced assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202) - # Send 102 blocks to node2. Block 102 will be rejected. - for i in range(101): - node2.send_message(msg_block(self.blocks[i])) - node2.sync_with_ping() # make sure the most recent block is synced - node2.send_message(msg_block(self.blocks[101])) - assert_equal(self.nodes[2].getblock(self.nodes[2].getbestblockhash())['height'], 101) + # Send blocks to node2. Block 102 will be rejected. + self.send_blocks_until_disconnected(node2) + self.assert_blockchain_height(self.nodes[2], 101) if __name__ == '__main__': - SendHeadersTest().main() + AssumeValidTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 0bd9d4afb47e..66e220407dfb 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -124,6 +124,7 @@ 'bip9-softforks.py', 'rpcbind_test.py', # vv Tests less than 30s vv + 'assumevalid.py', 'bip65-cltv.py', 'bip65-cltv-p2p.py', # NOTE: needs dash_hash to pass 'bipdersig-p2p.py', # NOTE: needs dash_hash to pass From 6bb55d5474278d7cdca83e5d004e53c9c1d4a9bc Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Mar 2017 10:34:13 +0200 Subject: [PATCH 069/987] Merge #10056: [zmq] Call va_end() on va_start()ed args. 5ba61f0 [zmq] Call va_end() on va_start()ed args. (Karl-Johan Alm) Tree-SHA512: fbd3a0c29308ca9607f362f14fa7ea9c949a3f25dc09a349fe3b3ffd316b573c86778e29d3b9d55c684571eacae50aca90bb872e2e5489818d0af8310511fe79 --- src/zmq/zmqpublishnotifier.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index f2a7b61b8881..e831401cfd54 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -39,6 +39,7 @@ static int zmq_send_multipart(void *sock, const void* data, size_t size, ...) if (rc != 0) { zmqError("Unable to initialize ZMQ msg"); + va_end(args); return -1; } @@ -52,6 +53,7 @@ static int zmq_send_multipart(void *sock, const void* data, size_t size, ...) { zmqError("Unable to send ZMQ msg"); zmq_msg_close(&msg); + va_end(args); return -1; } @@ -62,6 +64,7 @@ static int zmq_send_multipart(void *sock, const void* data, size_t size, ...) size = va_arg(args, size_t); } + va_end(args); return 0; } From c2258978bf11efdcef56940e0b498846d9081508 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 27 Mar 2017 10:36:32 +0200 Subject: [PATCH 070/987] Merge #10057: [init] Deduplicated sigaction() boilerplate 81a3857 Deduplicated sigaction() boilerplate (Thomas Snider) Tree-SHA512: 705b73f285a3d76504ba01476e072fdce67731b65f309bb04e4bbd765556c37e127cb769b475de2d68b33f50d7737fb136aefa0fa7c725a11ad16a47b9d0365f --- src/init.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index aee139e6e517..6b7e6bc647fe 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -374,18 +374,31 @@ void Shutdown() } /** - * Signal handlers are very limited in what they are allowed to do, so: + * Signal handlers are very limited in what they are allowed to do. + * The execution context the handler is invoked in is not guaranteed, + * so we restrict handler operations to just touching variables: */ -void HandleSIGTERM(int) +static void HandleSIGTERM(int) { fRequestShutdown = true; } -void HandleSIGHUP(int) +static void HandleSIGHUP(int) { fReopenDebugLog = true; } +#ifndef WIN32 +static void registerSignalHandler(int signal, void(*handler)(int)) +{ + struct sigaction sa; + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(signal, &sa, NULL); +} +#endif + bool static Bind(CConnman& connman, const CService &addr, unsigned int flags) { if (!(flags & BF_EXPLICIT) && IsLimited(addr)) return false; @@ -1064,19 +1077,11 @@ bool AppInitBasicSetup() } // Clean shutdown on SIGTERM - struct sigaction sa; - sa.sa_handler = HandleSIGTERM; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); + registerSignalHandler(SIGTERM, HandleSIGTERM); + registerSignalHandler(SIGINT, HandleSIGTERM); // Reopen debug.log on SIGHUP - struct sigaction sa_hup; - sa_hup.sa_handler = HandleSIGHUP; - sigemptyset(&sa_hup.sa_mask); - sa_hup.sa_flags = 0; - sigaction(SIGHUP, &sa_hup, NULL); + registerSignalHandler(SIGHUP, HandleSIGHUP); // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly signal(SIGPIPE, SIG_IGN); From e57559a8dafac9db389476ca5b529ba49d3860bd Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 28 Mar 2017 11:36:29 +0200 Subject: [PATCH 071/987] Merge #10096: Check that all test scripts in test/functional are being run 29d6634 Check that all test scripts in test/functional are being run (John Newbery) Tree-SHA512: 9231d3a119632be031c51c4f7e95a8adae58489a8ec36fc967d499c0708bae2941a3bf28f11dcd4efd59141eb54c3c920f2629f5cd8a0139d30397a19591666d --- test/functional/test_runner.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 66e220407dfb..4eca55f37e7b 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -140,6 +140,13 @@ ALL_SCRIPTS = BASE_SCRIPTS + ZMQ_SCRIPTS + EXTENDED_SCRIPTS +NON_SCRIPTS = [ + # These are python files that live in the functional tests directory, but are not test scripts. + "combine_logs.py", + "create_cache.py", + "test_runner.py", +] + def main(): # Parse arguments and pass through unrecognised args parser = argparse.ArgumentParser(add_help=False, @@ -225,6 +232,8 @@ def main(): subprocess.check_call([(config["environment"]["SRCDIR"] + '/test/functional/' + test_list[0].split()[0])] + ['-h']) sys.exit(0) + check_script_list(config["environment"]["SRCDIR"]) + run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args) def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=False, args=[]): @@ -344,6 +353,18 @@ def get_next(self): return name, stdout, stderr, status, int(time.time() - time0) print('.', end='', flush=True) +def check_script_list(src_dir): + """Check scripts directory. + + Check that there are no scripts in the functional tests directory which are + not being run by pull-tester.py.""" + script_dir = src_dir + '/test/functional/' + python_files = set([t for t in os.listdir(script_dir) if t[-3:] == ".py"]) + missed_tests = list(python_files - set(map(lambda x: x.split()[0], ALL_SCRIPTS + NON_SCRIPTS))) + if len(missed_tests) != 0: + print("The following scripts are not being run:" + str(missed_tests)) + print("Check the test lists in test_runner.py") + sys.exit(1) class RPCCoverage(object): """ From bfd63c179d0961c54e6795e17aa735ca47967aa4 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 28 Mar 2017 14:44:53 +0200 Subject: [PATCH 072/987] Merge #10076: [qa] combine_logs: Use ordered list for logfiles fa4535d [qa] combine_logs: Use ordered list for logfiles (MarcoFalke) Tree-SHA512: 66da6f2659018d24b1cac1f6d2ee8603c2c6f15ce5aff456e8e4b208874e97c7046b97112046d5b45bfd777b405771a3ad0a55036c4f4cdeec06842563af2c4d --- test/functional/combine_logs.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/functional/combine_logs.py b/test/functional/combine_logs.py index 0c2f60172fa1..3ca74ea35eac 100755 --- a/test/functional/combine_logs.py +++ b/test/functional/combine_logs.py @@ -6,8 +6,8 @@ import argparse from collections import defaultdict, namedtuple -import glob import heapq +import itertools import os import re import sys @@ -49,7 +49,10 @@ def read_logs(tmp_dir): for each of the input log files.""" files = [("test", "%s/test_framework.log" % tmp_dir)] - for i, logfile in enumerate(glob.glob("%s/node*/regtest/debug.log" % tmp_dir)): + for i in itertools.count(): + logfile = "{}/node{}/regtest/debug.log".format(tmp_dir, i) + if not os.path.isfile(logfile): + break files.append(("node%d" % i, logfile)) return heapq.merge(*[get_log_events(source, f) for source, f in files]) From 05cb5a058e07125bb718e03f39fce7cbb9343ec2 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 28 Mar 2017 18:17:25 -0700 Subject: [PATCH 073/987] Merge #10108: ApproximateBestSubset should take inputs by reference, not value 5335132 ApproximateBestSubset should take inputs by reference, not value (Ryan Havar) Tree-SHA512: 0990de7efbeba8ef9b70ccee45298c2fb982459a64e44b6395f7d28808740315d2d26e87103d4848677fc519cdf3247c1bde498ecb2e239e18134cb933e6b661 --- src/wallet/wallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 193ade4002de..a6e4a16d14a1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2558,7 +2558,7 @@ void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlySafe, const } } -static void ApproximateBestSubset(std::vector > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, +static void ApproximateBestSubset(const std::vector > >& vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, std::vector& vfBest, CAmount& nBest, bool fUseInstantSend = false, int iterations = 1000) { std::vector vfIncluded; @@ -4011,7 +4011,7 @@ bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) /** * Mark old keypool keys as used, - * and generate all new keys + * and generate all new keys */ bool CWallet::NewKeyPool() { From 404e244d1ba33ab0744abf7fd1a05ecd18f93719 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 29 Mar 2017 00:29:36 -0700 Subject: [PATCH 074/987] Merge #10088: Trivial: move several relay options into the relay help group 0fb2887 Move several relay options into the Relay help group (Jameson Lopp) Tree-SHA512: 31fdfd8c741adb6fe6806a28955f0fbbc9360b1d8c3d8a28684794822f1b3231fffab93357357d986b81a4532c9eeabb79e5ede9378ff3ad8930ceb6588d9eb6 --- src/init.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 6b7e6bc647fe..2ceeab77bdbd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -519,8 +519,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-whitebind=", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); strUsage += HelpMessageOpt("-whitelist=", _("Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) or CIDR notated network (e.g. 1.2.3.0/24). Can be specified multiple times.") + " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); - strUsage += HelpMessageOpt("-whitelistrelay", strprintf(_("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)"), DEFAULT_WHITELISTRELAY)); - strUsage += HelpMessageOpt("-whitelistforcerelay", strprintf(_("Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)"), DEFAULT_WHITELISTFORCERELAY)); strUsage += HelpMessageOpt("-maxuploadtarget=", strprintf(_("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)"), DEFAULT_MAX_UPLOAD_TARGET)); #ifdef ENABLE_WALLET @@ -583,8 +581,6 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxsigcachesize=", strprintf("Limit size of signature cache to MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE)); strUsage += HelpMessageOpt("-maxtipage=", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE)); } - strUsage += HelpMessageOpt("-minrelaytxfee=", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)"), - CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE))); strUsage += HelpMessageOpt("-maxtxfee=", strprintf(_("Maximum total fees (in %s) to use in a single wallet transaction or raw transaction; setting this too low may abort large transactions (default: %s)"), CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE))); strUsage += HelpMessageOpt("-printtoconsole", _("Send trace/debug info to console instead of debug.log file")); @@ -629,6 +625,10 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Minimum bytes per sigop in transactions we relay and mine (default: %u)"), DEFAULT_BYTES_PER_SIGOP)); strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER)); strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY)); + strUsage += HelpMessageOpt("-minrelaytxfee=", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)"), + CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE))); + strUsage += HelpMessageOpt("-whitelistrelay", strprintf(_("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)"), DEFAULT_WHITELISTRELAY)); + strUsage += HelpMessageOpt("-whitelistforcerelay", strprintf(_("Force relay of transactions from whitelisted peers even if they violate local relay policy (default: %d)"), DEFAULT_WHITELISTFORCERELAY)); strUsage += HelpMessageGroup(_("Block creation options:")); strUsage += HelpMessageOpt("-blockmaxsize=", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); From 94aa904c069b350a9d4d8884e52e5a39d61975a6 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 29 Mar 2017 11:16:42 +0200 Subject: [PATCH 075/987] Merge #10107: Remove unused variable. Remove accidental trailing semicolons in Python code 85de9d4 Remove call to gettransaction(...) where the result is unused (practicalswift) bd02422 Remove accidental trailing semicolons in Python code (practicalswift) Tree-SHA512: 23ffb1ccc29bf73b334d62b274ab614cb40e2969147adccacbaecc69a410a661a9f2dd9e9cbc8a70bd2c7f345095efc68743f288eb866315e0e8731441ba01d0 --- contrib/zmq/zmq_sub3.4.py | 2 +- test/functional/importmulti.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/zmq/zmq_sub3.4.py b/contrib/zmq/zmq_sub3.4.py index f84bb6fcd0f4..b0f7dd18ab4e 100755 --- a/contrib/zmq/zmq_sub3.4.py +++ b/contrib/zmq/zmq_sub3.4.py @@ -67,7 +67,7 @@ def handle(self) : msg = yield from self.zmqSubSocket.recv_multipart() topic = msg[0] body = msg[1] - sequence = "Unknown"; + sequence = "Unknown" if len(msg[-1]) == 4: msgSequence = struct.unpack(' Date: Thu, 30 Mar 2017 09:22:59 +0200 Subject: [PATCH 076/987] Merge #10109: Remove SingleNodeConnCB 159fe88 Remove SingleNodeConnCB (John Newbery) Tree-SHA512: 2fc3d060f4ac9445e657134919a871c46987d53eb98d23a858ee9515fc997be7a81923f08f2a37d07d123b55b912ae82ffa0f820d16297b044ab24dcf0788a8a --- test/functional/assumevalid.py | 7 +- test/functional/maxblocksinflight.py | 6 +- test/functional/maxuploadtarget.py | 2 +- test/functional/p2p-acceptblock.py | 2 +- test/functional/p2p-compactblocks.py | 4 +- test/functional/p2p-leaktests.py | 2 +- test/functional/p2p-mempool.py | 2 +- test/functional/p2p-timeouts.py | 4 +- test/functional/p2p-versionbits-warning.py | 2 +- test/functional/sendheaders.py | 4 +- test/functional/test_framework/comptool.py | 2 +- test/functional/test_framework/mininode.py | 120 +++++++++++---------- 12 files changed, 77 insertions(+), 80 deletions(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index da680a5d24ba..a9c2b17b4a11 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -40,17 +40,14 @@ CTxOut, NetworkThread, NodeConn, - SingleNodeConnCB, + NodeConnCB, msg_block, msg_headers) from test_framework.script import (CScript, OP_TRUE) from test_framework.test_framework import BitcoinTestFramework from test_framework.util import (start_node, p2p_port, assert_equal) -class BaseNode(SingleNodeConnCB): - def __init__(self): - super().__init__() - +class BaseNode(NodeConnCB): def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() headers_message.headers = [CBlockHeader(b) for b in new_blocks] diff --git a/test/functional/maxblocksinflight.py b/test/functional/maxblocksinflight.py index 9eaa254649fd..99ffea90eeae 100755 --- a/test/functional/maxblocksinflight.py +++ b/test/functional/maxblocksinflight.py @@ -17,7 +17,6 @@ MAX_REQUESTS = 128 class TestManager(NodeConnCB): - # set up NodeConnCB callbacks, overriding base class def on_getdata(self, conn, message): self.log.debug("got getdata %s" % repr(message)) # Log the requests @@ -30,11 +29,8 @@ def on_close(self, conn): if not self.disconnectOkay: raise EarlyDisconnectError(0) - def __init__(self): - NodeConnCB.__init__(self) - def add_new_connection(self, connection): - self.connection = connection + super().add_connection(connection) self.blockReqCounts = {} self.disconnectOkay = False diff --git a/test/functional/maxuploadtarget.py b/test/functional/maxuploadtarget.py index 1500e24b9961..b87b1c4d340d 100755 --- a/test/functional/maxuploadtarget.py +++ b/test/functional/maxuploadtarget.py @@ -20,7 +20,7 @@ # p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): def __init__(self): - NodeConnCB.__init__(self) + super().__init__() self.connection = None self.ping_counter = 1 self.last_pong = msg_pong() diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p-acceptblock.py index dfd463d5d62c..d230690c427d 100755 --- a/test/functional/p2p-acceptblock.py +++ b/test/functional/p2p-acceptblock.py @@ -58,7 +58,7 @@ # p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): def __init__(self): - NodeConnCB.__init__(self) + super().__init__() self.connection = None self.ping_counter = 1 self.last_pong = msg_pong() diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py index 56990612d4e2..900f9c142654 100755 --- a/test/functional/p2p-compactblocks.py +++ b/test/functional/p2p-compactblocks.py @@ -12,9 +12,9 @@ from test_framework.script import CScript, OP_TRUE # TestNode: A peer we use to send messages to bitcoind, and store responses. -class TestNode(SingleNodeConnCB): +class TestNode(NodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) + super().__init__() self.last_sendcmpct = [] self.last_headers = None self.last_inv = None diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p-leaktests.py index 44bbc5b0d402..205ec86a4c43 100755 --- a/test/functional/p2p-leaktests.py +++ b/test/functional/p2p-leaktests.py @@ -19,10 +19,10 @@ class CLazyNode(NodeConnCB): def __init__(self): + super().__init__() self.connection = None self.unexpected_msg = False self.connected = False - super().__init__() def add_connection(self, conn): self.connection = conn diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p-mempool.py index 0aa9c90e8f3d..3d3a9939d4a0 100755 --- a/test/functional/p2p-mempool.py +++ b/test/functional/p2p-mempool.py @@ -14,7 +14,7 @@ class TestNode(NodeConnCB): def __init__(self): - NodeConnCB.__init__(self) + super().__init__() self.connection = None self.ping_counter = 1 self.last_pong = msg_pong() diff --git a/test/functional/p2p-timeouts.py b/test/functional/p2p-timeouts.py index 498acb23fec5..de4edd6800c9 100755 --- a/test/functional/p2p-timeouts.py +++ b/test/functional/p2p-timeouts.py @@ -27,9 +27,9 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -class TestNode(SingleNodeConnCB): +class TestNode(NodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) + super().__init__() self.connected = False self.received_version = False diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py index dc714e9a4a3f..d4d03861a4ab 100755 --- a/test/functional/p2p-versionbits-warning.py +++ b/test/functional/p2p-versionbits-warning.py @@ -28,7 +28,7 @@ # p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): def __init__(self): - NodeConnCB.__init__(self) + super().__init__() self.connection = None self.ping_counter = 1 self.last_pong = msg_pong() diff --git a/test/functional/sendheaders.py b/test/functional/sendheaders.py index 83a2c45d020f..49266da5f1c7 100755 --- a/test/functional/sendheaders.py +++ b/test/functional/sendheaders.py @@ -92,9 +92,9 @@ direct_fetch_response_time = 0.05 -class BaseNode(SingleNodeConnCB): +class BaseNode(NodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) + super().__init__() self.last_inv = None self.last_headers = None self.last_block = None diff --git a/test/functional/test_framework/comptool.py b/test/functional/test_framework/comptool.py index 669a5c73afcc..f5c19001332b 100755 --- a/test/functional/test_framework/comptool.py +++ b/test/functional/test_framework/comptool.py @@ -42,7 +42,7 @@ def __repr__(self): class TestNode(NodeConnCB): def __init__(self, block_store, tx_store): - NodeConnCB.__init__(self) + super().__init__() self.conn = None self.bestblockhash = None self.block_store = block_store diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index 3ebf11540075..d7749fd46e90 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -1606,25 +1606,9 @@ def __init__(self): self.deliver_sleep_time = None # Remember the services our peer has advertised self.peer_services = None - - def set_deliver_sleep_time(self, value): - with mininode_lock: - self.deliver_sleep_time = value - - def get_deliver_sleep_time(self): - with mininode_lock: - return self.deliver_sleep_time - - # Spin until verack message is received from the node. - # Tests may want to use this as a signal that the test can begin. - # This can be called from the testing thread, so it needs to acquire the - # global lock. - def wait_for_verack(self): - while True: - with mininode_lock: - if self.verack_received: - return - time.sleep(0.05) + self.connection = None + self.ping_counter = 1 + self.last_pong = msg_pong() def deliver(self, conn, message): deliver_sleep = self.get_deliver_sleep_time() @@ -1636,17 +1620,36 @@ def deliver(self, conn, message): except: logger.exception("ERROR delivering %s" % repr(message)) - def on_version(self, conn, message): - if message.nVersion >= 209: - conn.send_message(msg_verack()) - conn.ver_send = min(MY_VERSION, message.nVersion) - if message.nVersion < 209: - conn.ver_recv = conn.ver_send - conn.nServices = message.nServices + def set_deliver_sleep_time(self, value): + with mininode_lock: + self.deliver_sleep_time = value - def on_verack(self, conn, message): - conn.ver_recv = conn.ver_send - self.verack_received = True + def get_deliver_sleep_time(self): + with mininode_lock: + return self.deliver_sleep_time + + # Callbacks which can be overridden by subclasses + ################################################# + + def on_addr(self, conn, message): pass + def on_alert(self, conn, message): pass + def on_block(self, conn, message): pass + def on_blocktxn(self, conn, message): pass + def on_close(self, conn): pass + def on_cmpctblock(self, conn, message): pass + def on_feefilter(self, conn, message): pass + def on_getaddr(self, conn, message): pass + def on_getblocks(self, conn, message): pass + def on_getblocktxn(self, conn, message): pass + def on_getdata(self, conn, message): pass + def on_getheaders(self, conn, message): pass + def on_headers(self, conn, message): pass + def on_mempool(self, conn): pass + def on_open(self, conn): pass + def on_reject(self, conn, message): pass + def on_sendcmpct(self, conn, message): pass + def on_sendheaders(self, conn, message): pass + def on_tx(self, conn, message): pass def on_inv(self, conn, message): want = msg_getdata() @@ -1656,39 +1659,31 @@ def on_inv(self, conn, message): if len(want.inv): conn.send_message(want) - def on_addr(self, conn, message): pass - def on_alert(self, conn, message): pass - def on_getdata(self, conn, message): pass - def on_getblocks(self, conn, message): pass - def on_tx(self, conn, message): pass - def on_block(self, conn, message): pass - def on_getaddr(self, conn, message): pass - def on_headers(self, conn, message): pass - def on_getheaders(self, conn, message): pass def on_ping(self, conn, message): if conn.ver_send > BIP0031_VERSION: conn.send_message(msg_pong(message.nonce)) - def on_reject(self, conn, message): pass - def on_open(self, conn): pass - def on_close(self, conn): pass - def on_mempool(self, conn): pass - def on_pong(self, conn, message): pass - def on_sendheaders(self, conn, message): pass - def on_sendcmpct(self, conn, message): pass - def on_cmpctblock(self, conn, message): pass - def on_getblocktxn(self, conn, message): pass - def on_blocktxn(self, conn, message): pass + + def on_pong(self, conn, message): + self.last_pong = message + def on_mnlistdiff(self, conn, message): pass def on_clsig(self, conn, message): pass def on_islock(self, conn, message): pass -# More useful callbacks and functions for NodeConnCB's which have a single NodeConn -class SingleNodeConnCB(NodeConnCB): - def __init__(self): - NodeConnCB.__init__(self) - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() + def on_verack(self, conn, message): + conn.ver_recv = conn.ver_send + self.verack_received = True + + def on_version(self, conn, message): + if message.nVersion >= 209: + conn.send_message(msg_verack()) + conn.ver_send = min(MY_VERSION, message.nVersion) + if message.nVersion < 209: + conn.ver_recv = conn.ver_send + conn.nServices = message.nServices + + # Helper functions + ################## def add_connection(self, conn): self.connection = conn @@ -1701,9 +1696,6 @@ def send_and_ping(self, message): self.send_message(message) self.sync_with_ping() - def on_pong(self, conn, message): - self.last_pong = message - # Sync up with the node def sync_with_ping(self, timeout=30): def received_pong(): @@ -1711,8 +1703,20 @@ def received_pong(): self.send_message(msg_ping(nonce=self.ping_counter)) success = wait_until(received_pong, timeout=timeout) self.ping_counter += 1 + return success + # Spin until verack message is received from the node. + # Tests may want to use this as a signal that the test can begin. + # This can be called from the testing thread, so it needs to acquire the + # global lock. + def wait_for_verack(self): + while True: + with mininode_lock: + if self.verack_received: + return + time.sleep(0.05) + # The actual NodeConn class # This class provides an interface for a p2p connection to a specified node class NodeConn(asyncore.dispatcher): From 4121daba28e40695c3fef1f7878ab1672eb1eb5d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 2 Apr 2017 11:58:19 +0200 Subject: [PATCH 077/987] Merge #10098: Make qt wallet test compatible with qt4 e9a6461 Make qt wallet test compatible with qt4 (Russell Yanofsky) Tree-SHA512: a3e4598986cb3c5c20aaa1d440abc886d84fcc69a6ee4079787cfc8e3a2dce655060ff95612cb15ce8b5a9b8911e4afe2281345b59a4353ec32edf3771338381 --- src/Makefile.qt.include | 3 +++ src/qt/callback.h | 30 ++++++++++++++++++++++++++++++ src/qt/test/wallettests.cpp | 9 ++++----- 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/qt/callback.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index a50bf431334e..9a49a45a5dfa 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -60,6 +60,7 @@ QT_MOC_CPP = \ qt/moc_bitcoinamountfield.cpp \ qt/moc_bitcoingui.cpp \ qt/moc_bitcoinunits.cpp \ + qt/moc_callback.cpp \ qt/moc_clientmodel.cpp \ qt/moc_coincontroldialog.cpp \ qt/moc_coincontroltreewidget.cpp \ @@ -107,6 +108,7 @@ BITCOIN_MM = \ QT_MOC = \ qt/dash.moc \ qt/bitcoinamountfield.moc \ + qt/callback.moc \ qt/intro.moc \ qt/overviewpage.moc \ qt/rpcconsole.moc @@ -129,6 +131,7 @@ BITCOIN_QT_H = \ qt/bitcoinamountfield.h \ qt/bitcoingui.h \ qt/bitcoinunits.h \ + qt/callback.h \ qt/clientmodel.h \ qt/coincontroldialog.h \ qt/coincontroltreewidget.h \ diff --git a/src/qt/callback.h b/src/qt/callback.h new file mode 100644 index 000000000000..a8b593a65255 --- /dev/null +++ b/src/qt/callback.h @@ -0,0 +1,30 @@ +#ifndef BITCOIN_QT_CALLBACK_H +#define BITCOIN_QT_CALLBACK_H + +#include + +class Callback : public QObject +{ + Q_OBJECT +public Q_SLOTS: + virtual void call() = 0; +}; + +template +class FunctionCallback : public Callback +{ + F f; + +public: + FunctionCallback(F f_) : f(std::move(f_)) {} + ~FunctionCallback() override {} + void call() override { f(this); } +}; + +template +FunctionCallback* makeCallback(F f) +{ + return new FunctionCallback(std::move(f)); +} + +#endif // BITCOIN_QT_CALLBACK_H diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 4d7767de8c1a..4656de90e20f 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -1,6 +1,7 @@ #include "wallettests.h" #include "qt/bitcoinamountfield.h" +#include "qt/callback.h" #include "qt/optionsmodel.h" #include "qt/platformstyle.h" #include "qt/qvalidatedlineedit.h" @@ -22,9 +23,7 @@ namespace //! Press "Yes" button in modal send confirmation dialog. void ConfirmSend() { - QTimer* timer = new QTimer; - timer->setSingleShot(true); - QObject::connect(timer, &QTimer::timeout, []() { + QTimer::singleShot(0, makeCallback([](Callback* callback) { for (QWidget* widget : QApplication::topLevelWidgets()) { if (widget->inherits("SendConfirmationDialog")) { SendConfirmationDialog* dialog = qobject_cast(widget); @@ -33,8 +32,8 @@ void ConfirmSend() button->click(); } } - }); - timer->start(0); + delete callback; + }), SLOT(call())); } //! Send coins to address and return txid. From 7fd979cc0eceb6a04c7b10743cbdc0ab51ac07f5 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 30 Mar 2017 21:27:15 +0200 Subject: [PATCH 078/987] Merge #10114: [tests] sync_with_ping should assert that ping hasn't timed out 6a18bb9 [tests] sync_with_ping should assert that ping hasn't timed out (John Newbery) 6426716 Add send_await_disconnect() method to p2p-compactblocks.py (John Newbery) Tree-SHA512: d0eeb066ed3f6aef594caaa693280d10abedac9b719e795c9659e52ddae315085eb2845131644793007e30a16e3e0bf3e3925b40ca2ae023cad923c5ab32df25 --- test/functional/assumevalid.py | 3 ++- test/functional/maxuploadtarget.py | 9 --------- test/functional/p2p-acceptblock.py | 15 -------------- test/functional/p2p-compactblocks.py | 23 ++++++++++++++++++++-- test/functional/p2p-mempool.py | 9 --------- test/functional/p2p-versionbits-warning.py | 15 -------------- test/functional/test_framework/mininode.py | 5 ++++- 7 files changed, 27 insertions(+), 52 deletions(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index a9c2b17b4a11..8e301c437922 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -190,7 +190,8 @@ def run_test(self): # Send all blocks to node1. All blocks will be accepted. for i in range(2202): node1.send_message(msg_block(self.blocks[i])) - node1.sync_with_ping() # make sure the most recent block is synced + # Syncing 2200 blocks can take a while on slow systems. Give it plenty of time to sync. + node1.sync_with_ping(120) assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202) # Send blocks to node2. Block 102 will be rejected. diff --git a/test/functional/maxuploadtarget.py b/test/functional/maxuploadtarget.py index b87b1c4d340d..efc2cdb5a639 100755 --- a/test/functional/maxuploadtarget.py +++ b/test/functional/maxuploadtarget.py @@ -68,15 +68,6 @@ def on_pong(self, conn, message): def on_close(self, conn): self.peer_disconnected = True - # Sync up with the node after delivery of a block - def sync_with_ping(self, timeout=30): - def received_pong(): - return (self.last_pong.nonce == self.ping_counter) - self.connection.send_message(msg_ping(nonce=self.ping_counter)) - success = wait_until(received_pong, timeout=timeout) - self.ping_counter += 1 - return success - class MaxUploadTest(BitcoinTestFramework): def __init__(self): diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p-acceptblock.py index d230690c427d..78b788d93f70 100755 --- a/test/functional/p2p-acceptblock.py +++ b/test/functional/p2p-acceptblock.py @@ -88,21 +88,6 @@ def send_message(self, message): def on_pong(self, conn, message): self.last_pong = message - # Sync up with the node after delivery of a block - def sync_with_ping(self, timeout=30): - self.connection.send_message(msg_ping(nonce=self.ping_counter)) - received_pong = False - sleep_time = 0.05 - while not received_pong and timeout > 0: - time.sleep(sleep_time) - timeout -= sleep_time - with mininode_lock: - if self.last_pong.nonce == self.ping_counter: - received_pong = True - self.ping_counter += 1 - return received_pong - - class AcceptBlockTest(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py index 900f9c142654..438ca0de0a42 100755 --- a/test/functional/p2p-compactblocks.py +++ b/test/functional/p2p-compactblocks.py @@ -29,6 +29,13 @@ def __init__(self): # This is for synchronizing the p2p message traffic, # so we can eg wait until a particular block is announced. self.set_announced_blockhashes = set() + self.connected = False + + def on_open(self, conn): + self.connected = True + + def on_close(self, conn): + self.connected = False def on_sendcmpct(self, conn, message): self.last_sendcmpct.append(message) @@ -104,6 +111,18 @@ def received_hash(): return (block_hash in self.set_announced_blockhashes) return wait_until(received_hash, timeout=timeout) + def send_await_disconnect(self, message, timeout=30): + """Sends a message to the node and wait for disconnect. + + This is used when we want to send a message into the node that we expect + will get us disconnected, eg an invalid block.""" + self.send_message(message) + success = wait_until(lambda: not self.connected, timeout=timeout) + if not success: + logger.error("send_await_disconnect failed!") + raise AssertionError("send_await_disconnect failed!") + return success + class CompactBlocksTest(BitcoinTestFramework): def __init__(self): super().__init__() @@ -260,8 +279,8 @@ def test_invalid_cmpctblock_message(self): # This index will be too high prefilled_txn = PrefilledTransaction(1, block.vtx[0]) cmpct_block.prefilled_txn = [prefilled_txn] - self.test_node.send_and_ping(msg_cmpctblock(cmpct_block)) - assert(int(self.nodes[0].getbestblockhash(), 16) == block.hashPrevBlock) + self.test_node.send_await_disconnect(msg_cmpctblock(cmpct_block)) + assert_equal(int(self.nodes[0].getbestblockhash(), 16), block.hashPrevBlock) # Compare the generated shortids to what we expect based on BIP 152, given # bitcoind's choice of nonce. diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p-mempool.py index 3d3a9939d4a0..5064ce74aab0 100755 --- a/test/functional/p2p-mempool.py +++ b/test/functional/p2p-mempool.py @@ -62,15 +62,6 @@ def on_pong(self, conn, message): def on_close(self, conn): self.peer_disconnected = True - # Sync up with the node after delivery of a block - def sync_with_ping(self, timeout=30): - def received_pong(): - return (self.last_pong.nonce == self.ping_counter) - self.connection.send_message(msg_ping(nonce=self.ping_counter)) - success = wait_until(received_pong, timeout=timeout) - self.ping_counter += 1 - return success - def send_mempool(self): self.lastInv = [] self.send_message(msg_mempool()) diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py index d4d03861a4ab..da960e2d804c 100755 --- a/test/functional/p2p-versionbits-warning.py +++ b/test/functional/p2p-versionbits-warning.py @@ -46,21 +46,6 @@ def send_message(self, message): def on_pong(self, conn, message): self.last_pong = message - # Sync up with the node after delivery of a block - def sync_with_ping(self, timeout=30): - self.connection.send_message(msg_ping(nonce=self.ping_counter)) - received_pong = False - sleep_time = 0.05 - while not received_pong and timeout > 0: - time.sleep(sleep_time) - timeout -= sleep_time - with mininode_lock: - if self.last_pong.nonce == self.ping_counter: - received_pong = True - self.ping_counter += 1 - return received_pong - - class VersionBitsWarningTest(BitcoinTestFramework): def __init__(self): super().__init__() diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index d7749fd46e90..e57af5b5597c 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -1697,11 +1697,14 @@ def send_and_ping(self, message): self.sync_with_ping() # Sync up with the node - def sync_with_ping(self, timeout=30): + def sync_with_ping(self, timeout=60): def received_pong(): return (self.last_pong.nonce == self.ping_counter) self.send_message(msg_ping(nonce=self.ping_counter)) success = wait_until(received_pong, timeout=timeout) + if not success: + logger.error("sync_with_ping failed!") + raise AssertionError("sync_with_ping failed!") self.ping_counter += 1 return success From c37008a450fda69187dfb3c4f11d537fb552fe30 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 20 May 2019 12:01:39 -0500 Subject: [PATCH 079/987] update dip4-coinbasemerkalroots.py and llmq-is-cl-conflicts.py Signed-off-by: Pasta --- test/functional/dip4-coinbasemerkleroots.py | 4 ++-- test/functional/llmq-is-cl-conflicts.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/functional/dip4-coinbasemerkleroots.py b/test/functional/dip4-coinbasemerkleroots.py index 66fcf01f56a5..b02c278e0cf3 100755 --- a/test/functional/dip4-coinbasemerkleroots.py +++ b/test/functional/dip4-coinbasemerkleroots.py @@ -16,9 +16,9 @@ ''' -class TestNode(SingleNodeConnCB): +class TestNode(NodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) + super().__init__() self.last_mnlistdiff = None def on_mnlistdiff(self, conn, message): diff --git a/test/functional/llmq-is-cl-conflicts.py b/test/functional/llmq-is-cl-conflicts.py index 4351728e856e..f376f3b7d68e 100755 --- a/test/functional/llmq-is-cl-conflicts.py +++ b/test/functional/llmq-is-cl-conflicts.py @@ -15,9 +15,9 @@ ''' -class TestNode(SingleNodeConnCB): +class TestNode(NodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) + super().__init__() self.clsigs = {} self.islocks = {} From bfeb5bca4c01550d9df88ff851be47491674ab0e Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 21 May 2019 11:03:15 +0300 Subject: [PATCH 080/987] fix txindex.py and add it to extended scripts --- test/functional/test_runner.py | 1 + test/functional/txindex.py | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 4eca55f37e7b..4cc657b8459d 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -132,6 +132,7 @@ 'getblocktemplate_proposals.py', 'txn_doublespend.py', 'txn_clone.py --mineblock', + 'txindex.py', 'forknotify.py', 'invalidateblock.py', 'maxblocksinflight.py', diff --git a/test/functional/txindex.py b/test/functional/txindex.py index 156017f63eb4..889d2eefc342 100755 --- a/test/functional/txindex.py +++ b/test/functional/txindex.py @@ -47,11 +47,12 @@ def run_test(self): privkey = "cU4zhap7nPJAWeMFu4j6jLrfPmqakDAzy8zn8Fhb3oEevdm4e5Lc" address = "yeMpGzMj3rhtnz48XsfpB8itPHhHtgxLc3" - addressHash = "C5E4FB9171C22409809A3E8047A29C83886E325D".decode("hex") + addressHash = binascii.unhexlify("C5E4FB9171C22409809A3E8047A29C83886E325D") scriptPubKey = CScript([OP_DUP, OP_HASH160, addressHash, OP_EQUALVERIFY, OP_CHECKSIG]) unspent = self.nodes[0].listunspent() tx = CTransaction() - amount = unspent[0]["amount"] * 100000000 + tx_fee_sat = 1000 + amount = int(unspent[0]["amount"] * 100000000) - tx_fee_sat tx.vin = [CTxIn(COutPoint(int(unspent[0]["txid"], 16), unspent[0]["vout"]))] tx.vout = [CTxOut(amount, scriptPubKey)] tx.rehash() @@ -62,9 +63,9 @@ def run_test(self): self.sync_all() # Check verbose raw transaction results - verbose = self.nodes[3].getrawtransaction(unspent[0]["txid"], 1) - assert_equal(verbose["vout"][0]["valueSat"], 5000000000); - assert_equal(verbose["vout"][0]["value"], 50); + verbose = self.nodes[3].getrawtransaction(txid, 1) + assert_equal(verbose["vout"][0]["valueSat"], 50000000000 - tx_fee_sat); + assert_equal(verbose["vout"][0]["value"] * 100000000, 50000000000 - tx_fee_sat); self.log.info("Passed") From 92fed92540959e30acad6c6d9870e24b7bd1b4b8 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 21 May 2019 16:52:59 +0300 Subject: [PATCH 081/987] Fix and re-enable pruning.py Pruning works when starting in -litemode --- src/init.cpp | 11 +++++++++-- test/functional/pruning.py | 18 +++++++++--------- test/functional/test_runner.py | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 2ceeab77bdbd..4dc06cfa361a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1213,8 +1213,15 @@ bool AppInitParameterInteraction() nPruneTarget = std::numeric_limits::max(); fPruneMode = true; } else if (nPruneTarget) { - if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { - return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); + if (GetBoolArg("-regtest", false)) { + // we use 1MB blocks to test this on regtest + if (nPruneTarget < 550 * 1024 * 1024) { + return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), 550)); + } + } else { + if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) { + return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024)); + } } LogPrintf("Prune configured to target %uMiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024); fPruneMode = true; diff --git a/test/functional/pruning.py b/test/functional/pruning.py index cc84c8c08572..74a9ebb5a328 100755 --- a/test/functional/pruning.py +++ b/test/functional/pruning.py @@ -45,15 +45,15 @@ def setup_network(self): self.nodes.append(start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900)) # Create node 2 to test pruning - self.nodes.append(start_node(2, self.options.tmpdir, ["-maxreceivebuffer=20000","-prune=550"], timewait=900)) + self.nodes.append(start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-maxreceivebuffer=20000","-prune=550"], redirect_stderr=True, timewait=900)) self.prunedir = self.options.tmpdir+"/node2/regtest/blocks/" # Create nodes 3 and 4 to test manual pruning (they will be re-started with manual pruning later) - self.nodes.append(start_node(3, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000"], timewait=900)) - self.nodes.append(start_node(4, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000"], timewait=900)) + self.nodes.append(start_node(3, self.options.tmpdir, ["-litemode","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], redirect_stderr=True, timewait=900)) + self.nodes.append(start_node(4, self.options.tmpdir, ["-litemode","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], redirect_stderr=True, timewait=900)) # Create nodes 5 to test wallet in prune mode, but do not connect - self.nodes.append(start_node(5, self.options.tmpdir, ["-prune=550"])) + self.nodes.append(start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], redirect_stderr=True)) # Determine default relay fee self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] @@ -228,13 +228,13 @@ def reorg_back(self): def manual_test(self, node_number, use_timestamp): # at this point, node has 995 blocks and has not yet run in prune mode - node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, timewait=900) + node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0"], redirect_stderr=True, timewait=900) assert_equal(node.getblockcount(), 995) assert_raises_jsonrpc(-1, "not in prune mode", node.pruneblockchain, 500) self.stop_node(node_number) # now re-start in manual pruning mode - node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-prune=1"], timewait=900) + node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=1"], redirect_stderr=True, timewait=900) assert_equal(node.getblockcount(), 995) def height(index): @@ -308,7 +308,7 @@ def has_block(index): # stop node, start back up with auto-prune at 550MB, make sure still runs self.stop_node(node_number) - self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-prune=550"], timewait=900) + self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], redirect_stderr=True, timewait=900) self.log.info("Success") @@ -316,7 +316,7 @@ def wallet_test(self): # check that the pruning node's wallet is still in good shape self.log.info("Stop and start pruning node to trigger wallet rescan") self.stop_node(2) - start_node(2, self.options.tmpdir, ["-prune=550"]) + start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], redirect_stderr=True) self.log.info("Success") # check that wallet loads loads successfully when restarting a pruned node after IBD. @@ -326,7 +326,7 @@ def wallet_test(self): nds = [self.nodes[0], self.nodes[5]] sync_blocks(nds, wait=5, timeout=300) self.stop_node(5) #stop and start to trigger rescan - start_node(5, self.options.tmpdir, ["-prune=550"]) + start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], redirect_stderr=True) self.log.info("Success") def run_test(self): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 4cc657b8459d..fbe3216b1c21 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -110,7 +110,7 @@ EXTENDED_SCRIPTS = [ # These tests are not run by the travis build process. # Longest test should go first, to favor running tests in parallel - # 'pruning.py', # Prune mode is incompatible with -txindex. + 'pruning.py', # NOTE: Prune mode is incompatible with -txindex, should work in litemode though. # vv Tests less than 20m vv 'smartfees.py', # vv Tests less than 5m vv From 6f91144f22e6085edd33f80700030ad54b47ffbb Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 21 May 2019 17:03:44 +0300 Subject: [PATCH 082/987] Fix p2p-fingerprint.py --- test/functional/p2p-fingerprint.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/functional/p2p-fingerprint.py b/test/functional/p2p-fingerprint.py index b59b66e1e42f..6c43cb95d6f8 100755 --- a/test/functional/p2p-fingerprint.py +++ b/test/functional/p2p-fingerprint.py @@ -16,7 +16,7 @@ CInv, NetworkThread, NodeConn, - SingleNodeConnCB, + NodeConnCB, msg_headers, msg_block, msg_getdata, @@ -90,14 +90,14 @@ def last_header_equals(self, expected_hash, node): # last month but that have over a month's worth of work are also withheld. def run_test(self): # TODO remove this when mininode is up-to-date with Bitcoin - class MyNodeConnCB(SingleNodeConnCB): + class MyNodeConnCB(NodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) + super().__init__() self.cond = threading.Condition() self.last_message = {} def deliver(self, conn, message): - SingleNodeConnCB.deliver(self, conn, message) + super().deliver(conn, message) command = message.command.decode('ascii') self.last_message[command] = message with self.cond: From 15fa1873d8d3b95a3d3199233c400fa8fbbb8c20 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 21 May 2019 11:01:57 +0300 Subject: [PATCH 083/987] Drop redundant imports and fix related code --- .../test_framework/test_framework.py | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index c955f5c3bd38..56e42f289c89 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -12,7 +12,6 @@ import tempfile import time from concurrent.futures import ThreadPoolExecutor -from time import time, sleep from .util import ( assert_equal, @@ -551,7 +550,7 @@ def send_complex_tx(self, sender, receiver): def wait_for_instantlock(self, txid, node): # wait for instantsend locks - start = time() + start = time.time() locked = False while True: try: @@ -562,17 +561,17 @@ def wait_for_instantlock(self, txid, node): except: # TX not received yet? pass - if time() > start + 10: + if time.time() > start + 10: break - sleep(0.5) + time.sleep(0.5) return locked def wait_for_sporks_same(self, timeout=30): - st = time() - while time() < st + timeout: + st = time.time() + while time.time() < st + timeout: if self.check_sporks_same(): return - sleep(0.5) + time.sleep(0.5) raise AssertionError("wait_for_sporks_same timed out") def check_sporks_same(self): @@ -584,8 +583,8 @@ def check_sporks_same(self): return True def wait_for_quorum_phase(self, phase, check_received_messages, check_received_messages_count, timeout=30): - t = time() - while time() - t < timeout: + t = time.time() + while time.time() - t < timeout: all_ok = True for mn in self.mninfo: s = mn.node.quorum("dkgstatus")["session"] @@ -605,12 +604,12 @@ def wait_for_quorum_phase(self, phase, check_received_messages, check_received_m break if all_ok: return - sleep(0.1) + time.sleep(0.1) raise AssertionError("wait_for_quorum_phase timed out") def wait_for_quorum_commitment(self, timeout = 15): - t = time() - while time() - t < timeout: + t = time.time() + while time.time() - t < timeout: all_ok = True for node in self.nodes: s = node.quorum("dkgstatus") @@ -623,7 +622,7 @@ def wait_for_quorum_commitment(self, timeout = 15): break if all_ok: return - sleep(0.1) + time.sleep(0.1) raise AssertionError("wait_for_quorum_commitment timed out") def mine_quorum(self, expected_contributions=5, expected_complaints=0, expected_justifications=0, expected_commitments=5): @@ -640,7 +639,7 @@ def mine_quorum(self, expected_contributions=5, expected_complaints=0, expected_ # Make sure all reached phase 1 (init) self.wait_for_quorum_phase(1, None, 0) # Give nodes some time to connect to neighbors - sleep(2) + time.sleep(2) set_mocktime(get_mocktime() + 1) set_node_times(self.nodes, get_mocktime()) self.nodes[0].generate(2) @@ -685,7 +684,7 @@ def mine_quorum(self, expected_contributions=5, expected_complaints=0, expected_ set_node_times(self.nodes, get_mocktime()) self.nodes[0].generate(1) while quorums == self.nodes[0].quorum("list"): - sleep(2) + time.sleep(2) set_mocktime(get_mocktime() + 1) set_node_times(self.nodes, get_mocktime()) self.nodes[0].generate(1) From 5652ea023733d8b401ae9ea13e4a097fa1c56c31 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Wed, 22 May 2019 08:35:51 +0200 Subject: [PATCH 084/987] Show number of InstantSend locks in Debug Console (#2919) * Implement GetInstantSendLockCount in CInstantSendManager * Add islockCountChanged signal to client model * Show number of InstantSend locks in debug console --- src/llmq/quorums_instantsend.cpp | 27 +++++++++++++++++++++++++++ src/llmq/quorums_instantsend.h | 3 +++ src/qt/clientmodel.cpp | 11 +++++++++++ src/qt/clientmodel.h | 3 +++ src/qt/forms/debugwindow.ui | 14 ++++++++++++++ src/qt/rpcconsole.cpp | 6 ++++++ src/qt/rpcconsole.h | 2 ++ 7 files changed, 66 insertions(+) diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index dd926430904c..807d9c7ed67b 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -185,6 +185,28 @@ bool CInstantSendDb::HasArchivedInstantSendLock(const uint256& islockHash) return db.Exists(std::make_tuple(std::string("is_a2"), islockHash)); } +size_t CInstantSendDb::GetInstantSendLockCount() +{ + auto it = std::unique_ptr(db.NewIterator()); + auto firstKey = std::make_tuple(std::string("is_i"), uint256()); + + it->Seek(firstKey); + + size_t cnt = 0; + while (it->Valid()) { + decltype(firstKey) curKey; + if (!it->GetKey(curKey) || std::get<0>(curKey) != "is_i") { + break; + } + + cnt++; + + it->Next(); + } + + return cnt; +} + CInstantSendLockPtr CInstantSendDb::GetInstantSendLockByHash(const uint256& hash) { CInstantSendLockPtr ret; @@ -1410,6 +1432,11 @@ CInstantSendLockPtr CInstantSendManager::GetConflictingLock(const CTransaction& return nullptr; } +size_t CInstantSendManager::GetInstantSendLockCount() +{ + return db.GetInstantSendLockCount(); +} + void CInstantSendManager::WorkThreadMain() { while (!workInterrupt) { diff --git a/src/llmq/quorums_instantsend.h b/src/llmq/quorums_instantsend.h index 955b1322355d..456ba44bb707 100644 --- a/src/llmq/quorums_instantsend.h +++ b/src/llmq/quorums_instantsend.h @@ -62,6 +62,7 @@ class CInstantSendDb std::unordered_map RemoveConfirmedInstantSendLocks(int nUntilHeight); void RemoveArchivedInstantSendLocks(int nUntilHeight); bool HasArchivedInstantSendLock(const uint256& islockHash); + size_t GetInstantSendLockCount(); CInstantSendLockPtr GetInstantSendLockByHash(const uint256& hash); uint256 GetInstantSendLockHashByTxid(const uint256& txid); @@ -159,6 +160,8 @@ class CInstantSendManager : public CRecoveredSigsListener bool AlreadyHave(const CInv& inv); bool GetInstantSendLockByHash(const uint256& hash, CInstantSendLock& ret); + size_t GetInstantSendLockCount(); + void WorkThreadMain(); }; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index b8db9017399b..0a636c476d06 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -23,6 +23,8 @@ #include "masternode/masternode-sync.h" #include "privatesend/privatesend.h" +#include "llmq/quorums_instantsend.h" + #include #include @@ -161,6 +163,14 @@ size_t ClientModel::getMempoolDynamicUsage() const return mempool.DynamicMemoryUsage(); } +size_t ClientModel::getInstantSentLockCount() const +{ + if (!llmq::quorumInstantSendManager) { + return 0; + } + return llmq::quorumInstantSendManager->GetInstantSendLockCount(); +} + double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const { CBlockIndex *tip = const_cast(tipIn); @@ -177,6 +187,7 @@ void ClientModel::updateTimer() // no locking required at this point // the following calls will acquire the required lock Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage()); + Q_EMIT islockCountChanged(getInstantSentLockCount()); Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); } diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index d3b429f0b4a0..846a71d46a85 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -63,6 +63,8 @@ class ClientModel : public QObject long getMempoolSize() const; //! Return the dynamic memory usage of the mempool size_t getMempoolDynamicUsage() const; + //! Return number of ISLOCKs + size_t getInstantSentLockCount() const; void setMasternodeList(const CDeterministicMNList& mnList); CDeterministicMNList getMasternodeList() const; @@ -117,6 +119,7 @@ class ClientModel : public QObject void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress, bool header); void additionalDataSyncProgressChanged(double nSyncProgress); void mempoolSizeChanged(long count, size_t mempoolSizeInBytes); + void islockCountChanged(size_t count); void networkActiveChanged(bool networkActive); void alertsChanged(const QString &warnings); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); diff --git a/src/qt/forms/debugwindow.ui b/src/qt/forms/debugwindow.ui index 0710120a39a1..5853f48b6fe8 100644 --- a/src/qt/forms/debugwindow.ui +++ b/src/qt/forms/debugwindow.ui @@ -408,6 +408,20 @@ + + + + InstantSend locks + + + + + + + N/A + + + diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 01f5c4aeecf0..cb1a80c12940 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -563,6 +563,7 @@ void RPCConsole::setClientModel(ClientModel *model) connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); connect(model, SIGNAL(mempoolSizeChanged(long,size_t)), this, SLOT(setMempoolSize(long,size_t))); + connect(model, SIGNAL(islockCountChanged(size_t)), this, SLOT(setInstantSendLockCount(size_t))); // set up peer table ui->peerWidget->setModel(model->getPeerTableModel()); @@ -906,6 +907,11 @@ void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage) ui->mempoolSize->setText(QString::number(dynUsage/1000000.0, 'f', 2) + " MB"); } +void RPCConsole::setInstantSendLockCount(size_t count) +{ + ui->instantSendLockCount->setText(QString::number(count)); +} + void RPCConsole::on_lineEdit_returnPressed() { QString cmd = ui->lineEdit->text(); diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h index 8f195cde5a77..c1466cf44fc6 100644 --- a/src/qt/rpcconsole.h +++ b/src/qt/rpcconsole.h @@ -111,6 +111,8 @@ public Q_SLOTS: void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers); /** Set size (number of transactions and memory usage) of the mempool in the UI */ void setMempoolSize(long numberOfTxs, size_t dynUsage); + /** Set number of InstantSend locks */ + void setInstantSendLockCount(size_t count); /** Go forward or back in history */ void browseHistory(int offset); /** Scroll console view to end */ From 7c05aa82130fb185e96c1d78bb5538d1a6f5ebc8 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Wed, 22 May 2019 21:49:05 +0200 Subject: [PATCH 085/987] Also gracefully timeout Travis builds when building source takes >30min (#2932) We assume 15-20 minutes for running integration tests, so we can spend a maximum of 30 minutes for building depends and source. --- .travis.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index ab605349d8ff..3930a2319ddc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,13 +71,14 @@ script: - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1` # Our scripts try to be Travis agnostic - $DOCKER_RUN_IN_BUILDER ./ci/build_depends.sh; - # Gracefully stop build without running into timeouts (which won't update caches) when building depends took too long - # Next build should fix this situation as it will start with a populated depends cache - - if [ $SECONDS -gt 1200 ]; then export DEPENDS_TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 - - test "$DEPENDS_TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh - - test "$DEPENDS_TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_unittests.sh - - test "$DEPENDS_TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh --jobs=3 - - test "$DEPENDS_TIMEOUT" != "true" && if [ "$DOCKER_BUILD" = "true" ]; then BUILD_DIR=build-ci/dashcore-$BUILD_TARGET ./docker/build-docker.sh; fi + # Gracefully stop build without running into timeouts (which won't update caches) when building depends or source took too long + # Next build should fix this situation as it will start with a populated cache + - if [ $SECONDS -gt 1200 ]; then export TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 + - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh + - if [ $SECONDS -gt 1800 ]; then export TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 + - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_unittests.sh + - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh --jobs=3 + - test "$TIMEOUT" != "true" && if [ "$DOCKER_BUILD" = "true" ]; then BUILD_DIR=build-ci/dashcore-$BUILD_TARGET ./docker/build-docker.sh; fi after_script: - echo $TRAVIS_COMMIT_RANGE - echo $TRAVIS_COMMIT_LOG From f1fe24b676b85991d2c53fc571e27c1fbc66e90e Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Wed, 22 May 2019 23:21:21 +0200 Subject: [PATCH 086/987] Only gracefully timeout Travis when integration tests need to be run (#2933) * Split RUN_TESTS into RUN_UNITTESTS and RUN_INTEGRATIONTESTS * Only gracefully timeout when RUN_INTEGRATIONTESTS=true --- .travis.yml | 2 +- ci/matrix.sh | 16 +++++++++++----- ci/test_integrationtests.sh | 2 +- ci/test_unittests.sh | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3930a2319ddc..0c01d73825eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -75,8 +75,8 @@ script: # Next build should fix this situation as it will start with a populated cache - if [ $SECONDS -gt 1200 ]; then export TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh - - if [ $SECONDS -gt 1800 ]; then export TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_unittests.sh + - if [ $SECONDS -gt 1800 -a "$RUN_INTEGRATIONTESTS" = "true" ]; then export TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh --jobs=3 - test "$TIMEOUT" != "true" && if [ "$DOCKER_BUILD" = "true" ]; then BUILD_DIR=build-ci/dashcore-$BUILD_TARGET ./docker/build-docker.sh; fi after_script: diff --git a/ci/matrix.sh b/ci/matrix.sh index e033ee3d5ef1..c91dec946ddd 100755 --- a/ci/matrix.sh +++ b/ci/matrix.sh @@ -30,6 +30,9 @@ export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks} export PYTHON_DEBUG=1 export MAKEJOBS="-j4" +export RUN_UNITTESTS=false +export RUN_INTEGRATIONTESTS=false + if [ "$BUILD_TARGET" = "arm-linux" ]; then export HOST=arm-linux-gnueabihf export PACKAGES="g++-arm-linux-gnueabihf" @@ -41,21 +44,22 @@ elif [ "$BUILD_TARGET" = "win32" ]; then export PACKAGES="python3 nsis g++-mingw-w64-i686 wine-stable wine32 bc" export BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --disable-miner" export DIRECT_WINE_EXEC_TESTS=true - export RUN_TESTS=true + export RUN_UNITTESTS=true elif [ "$BUILD_TARGET" = "win64" ]; then export HOST=x86_64-w64-mingw32 export DPKG_ADD_ARCH="i386" export PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-stable wine64 bc" export BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --disable-miner" export DIRECT_WINE_EXEC_TESTS=true - export RUN_TESTS=true + export RUN_UNITTESTS=true elif [ "$BUILD_TARGET" = "linux32" ]; then export HOST=i686-pc-linux-gnu export PACKAGES="g++-multilib bc python3-zmq" export BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports --enable-stacktraces LDFLAGS=-static-libstdc++" export USE_SHELL="/bin/dash" export PYZMQ=true - export RUN_TESTS=true + export RUN_UNITTESTS=true + export RUN_INTEGRATIONTESTS=true elif [ "$BUILD_TARGET" = "linux64" ]; then export HOST=x86_64-unknown-linux-gnu export PACKAGES="bc python3-zmq" @@ -63,19 +67,21 @@ elif [ "$BUILD_TARGET" = "linux64" ]; then export BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports --enable-stacktraces" export CPPFLAGS="-DDEBUG_LOCKORDER -DENABLE_DASH_DEBUG" export PYZMQ=true - export RUN_TESTS=true + export RUN_UNITTESTS=true + export RUN_INTEGRATIONTESTS=true elif [ "$BUILD_TARGET" = "linux64_nowallet" ]; then export HOST=x86_64-unknown-linux-gnu export PACKAGES="python3" export DEP_OPTS="NO_WALLET=1" export BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports" - export RUN_TESTS=true + export RUN_UNITTESTS=true elif [ "$BUILD_TARGET" = "linux64_release" ]; then export HOST=x86_64-unknown-linux-gnu export PACKAGES="bc python3-zmq" export DEP_OPTS="NO_UPNP=1" export BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports" export PYZMQ=true + export RUN_UNITTESTS=true elif [ "$BUILD_TARGET" = "mac" ]; then export HOST=x86_64-apple-darwin11 export PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools" diff --git a/ci/test_integrationtests.sh b/ci/test_integrationtests.sh index 0edc9d651371..1210291c8e2d 100755 --- a/ci/test_integrationtests.sh +++ b/ci/test_integrationtests.sh @@ -8,7 +8,7 @@ PASS_ARGS="$@" source ./ci/matrix.sh -if [ "$RUN_TESTS" != "true" ]; then +if [ "$RUN_INTEGRATIONTESTS" != "true" ]; then echo "Skipping integration tests" exit 0 fi diff --git a/ci/test_unittests.sh b/ci/test_unittests.sh index 2d221c66b683..1a6aecd2909e 100755 --- a/ci/test_unittests.sh +++ b/ci/test_unittests.sh @@ -6,7 +6,7 @@ set -e source ./ci/matrix.sh -if [ "$RUN_TESTS" != "true" ]; then +if [ "$RUN_UNITTESTS" != "true" ]; then echo "Skipping unit tests" exit 0 fi From 29194b1f5a503902fe710551f996df7008d6e9cc Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Wed, 22 May 2019 16:51:39 -0500 Subject: [PATCH 087/987] Backport Bitcoin#9424, Bitcoin#10123 and Bitcoin#10153 (#2918) * Contains dashification. disables `-debug dash` Merge #9424: Change LogAcceptCategory to use uint32_t rather than sets of strings. 6b3bb3d Change LogAcceptCategory to use uint32_t rather than sets of strings. (Gregory Maxwell) Tree-SHA512: ebb5bcf9a7d00a32dd1390b727ff4d29330a038423611da01268d8e1d2c0229e52a1098e751d4e6db73ef4ae862e1e96d38249883fcaf12b68f55ebb01035b34 Signed-off-by: Pasta 31 -> 32 Signed-off-by: Pasta * Merge #10123: Allow debug logs to be excluded from specified component 3bde556 Add -debugexclude option to switch off logging for specified components (John Newbery) Tree-SHA512: 30202e3f2085fc2fc5dd4bedb92988f4cb162c612a42cf8f6395a7da326f34975ddc347f82bc4ddca6c84c438dc0cc6e87869f90c7ff88105dbeaa52a947fa43 * bump to uint64_t due to added Dash codes Signed-off-by: Pasta * bump to uint64_t due to added Dash codes cont. Signed-off-by: Pasta * string -> BCLog format Signed-off-by: Pasta * uint32_t -> uint64_t Signed-off-by: Pasta * Fix CBatchedLogger * Fix most fDebug-s * Fix `debug` rpc * Fix BENCH and RAND conflicts * Add ALERT and use it * Update LogPrint-s in dash-specific code * Tweak few log categories Specifically: - use PRIVATESEND in `CPrivateSendClientManager::GetRandomNotUsedMasternode()` - use ZMQ in `CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote()` and `CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject()` * Drop no longer used MASTERNODE category * Merge #10153: logging: Fix off-by-one for shrinkdebugfile default faab624 logging: Fix off-by-one for shrinkdebugfile (MarcoFalke) Tree-SHA512: d6153e06067906172ff0611af9e585a3ecf0a7d56925b6ad7c12e75aa802441047059b9b6f6c78e79916c3f2abc8f1998bfd2d5b84201ec6421f727c08da3c21 * Shift dash-specific log categories to start from `1ul << 32` to avoid potential future conflicts with bitcoin ones * Fix `dash` category * remove debugCategories Signed-off-by: Pasta * Prepend "std::" to find call * Check for BCLog::PRIVATESEND instead of logCategories != BCLog::NONE * Use BCLog::MNPAYMENTS category instead of checking for logCategories != BCLog::NONE * Move "End Dash" comment below "ALERT" When adding new entries here, we'll otherwise get confused with ordering and might end up forgetting that adding something Dash specific must continue with the bit after 43. --- src/addrman.cpp | 2 +- src/addrman.h | 12 +- src/alert.cpp | 8 +- src/batchedlogger.cpp | 4 +- src/batchedlogger.h | 2 +- src/blockencodings.cpp | 9 +- src/dbwrapper.cpp | 3 +- src/evo/cbtx.cpp | 20 +-- src/evo/mnauth.cpp | 8 +- src/evo/specialtx.cpp | 8 +- src/governance/governance-classes.cpp | 52 ++++---- src/governance/governance-object.cpp | 24 ++-- src/governance/governance-object.h | 4 +- src/governance/governance-vote.cpp | 14 +-- src/governance/governance.cpp | 80 ++++++------ src/governance/governance.h | 2 +- src/httprpc.cpp | 6 +- src/httpserver.cpp | 39 +++--- src/init.cpp | 42 +++++-- src/instantsend.cpp | 88 ++++++------- src/keepass.cpp | 26 ++-- src/llmq/quorums.cpp | 20 +-- src/llmq/quorums_blockprocessor.cpp | 4 +- src/llmq/quorums_chainlocks.cpp | 12 +- src/llmq/quorums_dkgsession.cpp | 2 +- src/llmq/quorums_dkgsessionhandler.cpp | 8 +- src/llmq/quorums_instantsend.cpp | 30 ++--- src/llmq/quorums_signing.cpp | 22 ++-- src/llmq/quorums_signing_shares.cpp | 42 +++---- src/masternode/masternode-payments.cpp | 32 ++--- src/masternode/masternode-sync.cpp | 12 +- src/miner.cpp | 2 +- src/net.cpp | 62 ++++----- src/net.h | 10 +- src/net_processing.cpp | 165 ++++++++++++------------ src/netbase.cpp | 8 +- src/policy/fees.cpp | 26 ++-- src/privatesend/privatesend-client.cpp | 116 ++++++++--------- src/privatesend/privatesend-server.cpp | 100 +++++++-------- src/privatesend/privatesend.cpp | 16 +-- src/qt/coincontroldialog.cpp | 2 +- src/qt/dash.cpp | 14 ++- src/qt/overviewpage.cpp | 4 +- src/qt/transactiondesc.cpp | 2 +- src/random.cpp | 2 +- src/rpc/blockchain.cpp | 2 +- src/rpc/governance.cpp | 6 +- src/rpc/misc.cpp | 22 ++-- src/rpc/server.cpp | 13 +- src/spork.cpp | 12 +- src/timedata.cpp | 17 +-- src/torcontrol.cpp | 37 +++--- src/txdb.cpp | 2 +- src/txmempool.cpp | 7 +- src/util.cpp | 166 ++++++++++++++++--------- src/util.h | 64 +++++++++- src/validation.cpp | 53 ++++---- src/wallet/db.cpp | 18 +-- src/wallet/rpcwallet.cpp | 4 +- src/wallet/wallet.cpp | 28 ++--- src/wallet/walletdb.cpp | 2 +- src/zmq/zmqnotificationinterface.cpp | 12 +- src/zmq/zmqpublishnotifier.cpp | 32 ++--- 63 files changed, 904 insertions(+), 759 deletions(-) diff --git a/src/addrman.cpp b/src/addrman.cpp index ffc8a6955f3f..48b8dabd311a 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -248,7 +248,7 @@ void CAddrMan::Good_(const CService& addr, int64_t nTime) if (nUBucket == -1) return; - LogPrint("addrman", "Moving %s to tried\n", addr.ToString()); + LogPrint(BCLog::ADDRMAN, "Moving %s to tried\n", addr.ToString()); // move nId to the tried tables MakeTried(info, nId); diff --git a/src/addrman.h b/src/addrman.h index cdb4a65a65ce..413bf45277b5 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -445,7 +445,7 @@ class CAddrMan } } if (nLost + nLostUnk > 0) { - LogPrint("addrman", "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost); + LogPrint(BCLog::ADDRMAN, "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost); } Check(); @@ -511,8 +511,9 @@ class CAddrMan Check(); fRet |= Add_(addr, source, nTimePenalty); Check(); - if (fRet) - LogPrint("addrman", "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort(), source.ToString(), nTried, nNew); + if (fRet) { + LogPrint(BCLog::ADDRMAN, "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort(), source.ToString(), nTried, nNew); + } return fRet; } @@ -525,8 +526,9 @@ class CAddrMan for (std::vector::const_iterator it = vAddr.begin(); it != vAddr.end(); it++) nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0; Check(); - if (nAdd) - LogPrint("addrman", "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew); + if (nAdd) { + LogPrint(BCLog::ADDRMAN, "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew); + } return nAdd > 0; } diff --git a/src/alert.cpp b/src/alert.cpp index 5a634afceff3..59c8b10b03f5 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -226,13 +226,13 @@ bool CAlert::ProcessAlert(const std::vector& alertKey, bool fThre const CAlert& alert = (*mi).second; if (Cancels(alert)) { - LogPrint("alert", "cancelling alert %d\n", alert.nID); + LogPrint(BCLog::ALERT, "cancelling alert %d\n", alert.nID); uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); mapAlerts.erase(mi++); } else if (!alert.IsInEffect()) { - LogPrint("alert", "expiring alert %d\n", alert.nID); + LogPrint(BCLog::ALERT, "expiring alert %d\n", alert.nID); uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); mapAlerts.erase(mi++); } @@ -246,7 +246,7 @@ bool CAlert::ProcessAlert(const std::vector& alertKey, bool fThre const CAlert& alert = item.second; if (alert.Cancels(*this)) { - LogPrint("alert", "alert already cancelled by %d\n", alert.nID); + LogPrint(BCLog::ALERT, "alert already cancelled by %d\n", alert.nID); return false; } } @@ -261,7 +261,7 @@ bool CAlert::ProcessAlert(const std::vector& alertKey, bool fThre } } - LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); + LogPrint(BCLog::ALERT, "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); return true; } diff --git a/src/batchedlogger.cpp b/src/batchedlogger.cpp index 528562414ed1..e2a75bb31742 100644 --- a/src/batchedlogger.cpp +++ b/src/batchedlogger.cpp @@ -5,8 +5,8 @@ #include "batchedlogger.h" #include "util.h" -CBatchedLogger::CBatchedLogger(const std::string& _category, const std::string& _header) : - accept(LogAcceptCategory(_category.c_str())), header(_header) +CBatchedLogger::CBatchedLogger(uint64_t _category, const std::string& _header) : + accept(LogAcceptCategory(_category)), header(_header) { } diff --git a/src/batchedlogger.h b/src/batchedlogger.h index e3774ac3bf98..e778ebdb5ff2 100644 --- a/src/batchedlogger.h +++ b/src/batchedlogger.h @@ -14,7 +14,7 @@ class CBatchedLogger std::string header; std::string msg; public: - CBatchedLogger(const std::string& _category, const std::string& _header); + CBatchedLogger(uint64_t _category, const std::string& _header); virtual ~CBatchedLogger(); template diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index da4ce1392de7..02cac61e741d 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -164,7 +164,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c break; } - LogPrint("cmpctblock", "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, SER_NETWORK, PROTOCOL_VERSION)); + LogPrint(BCLog::CMPCTBLOCK, "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, SER_NETWORK, PROTOCOL_VERSION)); return READ_STATUS_OK; } @@ -209,10 +209,11 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector< return READ_STATUS_CHECKBLOCK_FAILED; } - LogPrint("cmpctblock", "Successfully reconstructed block %s with %lu txn prefilled, %lu txn from mempool (incl at least %lu from extra pool) and %lu txn requested\n", hash.ToString(), prefilled_count, mempool_count, extra_count, vtx_missing.size()); + LogPrint(BCLog::CMPCTBLOCK, "Successfully reconstructed block %s with %lu txn prefilled, %lu txn from mempool (incl at least %lu from extra pool) and %lu txn requested\n", hash.ToString(), prefilled_count, mempool_count, extra_count, vtx_missing.size()); if (vtx_missing.size() < 5) { - for (const auto& tx : vtx_missing) - LogPrint("cmpctblock", "Reconstructed block %s required tx %s\n", hash.ToString(), tx->GetHash().ToString()); + for (const auto& tx : vtx_missing) { + LogPrint(BCLog::CMPCTBLOCK, "Reconstructed block %s required tx %s\n", hash.ToString(), tx->GetHash().ToString()); + } } return READ_STATUS_OK; diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 3ad393b26121..aa5dc34d0884 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -21,8 +21,9 @@ class CBitcoinLevelDBLogger : public leveldb::Logger { // This code is adapted from posix_logger.h, which is why it is using vsprintf. // Please do not do this in normal code virtual void Logv(const char * format, va_list ap) override { - if (!LogAcceptCategory("leveldb")) + if (!LogAcceptCategory(BCLog::LEVELDB)) { return; + } char buffer[500]; for (int iter = 0; iter < 2; iter++) { char* base; diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 85ed1c297e98..12646b2a4d29 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -67,7 +67,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CValid } int64_t nTime2 = GetTimeMicros(); nTimePayload += nTime2 - nTime1; - LogPrint("bench", " - GetTxPayload: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimePayload * 0.000001); + LogPrint(BCLog::BENCHMARK, " - GetTxPayload: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimePayload * 0.000001); if (pindex) { uint256 calculatedMerkleRoot; @@ -79,7 +79,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CValid } int64_t nTime3 = GetTimeMicros(); nTimeMerkleMNL += nTime3 - nTime2; - LogPrint("bench", " - CalcCbTxMerkleRootMNList: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeMerkleMNL * 0.000001); + LogPrint(BCLog::BENCHMARK, " - CalcCbTxMerkleRootMNList: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeMerkleMNL * 0.000001); if (cbTx.nVersion >= 2) { if (!CalcCbTxMerkleRootQuorums(block, pindex->pprev, calculatedMerkleRoot, state)) { @@ -91,7 +91,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, CValid } int64_t nTime4 = GetTimeMicros(); nTimeMerkleQuorum += nTime4 - nTime3; - LogPrint("bench", " - CalcCbTxMerkleRootQuorums: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkleQuorum * 0.000001); + LogPrint(BCLog::BENCHMARK, " - CalcCbTxMerkleRootQuorums: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkleQuorum * 0.000001); } @@ -114,12 +114,12 @@ bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev } int64_t nTime2 = GetTimeMicros(); nTimeDMN += nTime2 - nTime1; - LogPrint("bench", " - BuildNewListFromBlock: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeDMN * 0.000001); + LogPrint(BCLog::BENCHMARK, " - BuildNewListFromBlock: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeDMN * 0.000001); CSimplifiedMNList sml(tmpMNList); int64_t nTime3 = GetTimeMicros(); nTimeSMNL += nTime3 - nTime2; - LogPrint("bench", " - CSimplifiedMNList: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeSMNL * 0.000001); + LogPrint(BCLog::BENCHMARK, " - CSimplifiedMNList: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeSMNL * 0.000001); static CSimplifiedMNList smlCached; static uint256 merkleRootCached; @@ -134,7 +134,7 @@ bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev merkleRootRet = sml.CalcMerkleRoot(&mutated); int64_t nTime4 = GetTimeMicros(); nTimeMerkle += nTime4 - nTime3; - LogPrint("bench", " - CalcMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkle * 0.000001); + LogPrint(BCLog::BENCHMARK, " - CalcMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkle * 0.000001); smlCached = std::move(sml); merkleRootCached = merkleRootRet; @@ -160,7 +160,7 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre size_t hashCount = 0; int64_t nTime2 = GetTimeMicros(); nTimeMinedAndActive += nTime2 - nTime1; - LogPrint("bench", " - GetMinedAndActiveCommitmentsUntilBlock: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeMinedAndActive * 0.000001); + LogPrint(BCLog::BENCHMARK, " - GetMinedAndActiveCommitmentsUntilBlock: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeMinedAndActive * 0.000001); if (quorums == quorumsCached) { qcHashes = qcHashesCached; @@ -182,7 +182,7 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre } int64_t nTime3 = GetTimeMicros(); nTimeMined += nTime3 - nTime2; - LogPrint("bench", " - GetMinedCommitment: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeMined * 0.000001); + LogPrint(BCLog::BENCHMARK, " - GetMinedCommitment: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeMined * 0.000001); // now add the commitments from the current block, which are not returned by GetMinedAndActiveCommitmentsUntilBlock // due to the use of pindexPrev (we don't have the tip index here) @@ -220,13 +220,13 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre std::sort(qcHashesVec.begin(), qcHashesVec.end()); int64_t nTime4 = GetTimeMicros(); nTimeLoop += nTime4 - nTime3; - LogPrint("bench", " - Loop: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeLoop * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Loop: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeLoop * 0.000001); bool mutated = false; merkleRootRet = ComputeMerkleRoot(qcHashesVec, &mutated); int64_t nTime5 = GetTimeMicros(); nTimeMerkle += nTime5 - nTime4; - LogPrint("bench", " - ComputeMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001); + LogPrint(BCLog::BENCHMARK, " - ComputeMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001); return !mutated; } diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 7592d24cb13d..be2ce65c000b 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -39,7 +39,7 @@ void CMNAuth::PushMNAUTH(CNode* pnode, CConnman& connman) mnauth.proRegTxHash = activeMasternodeInfo.proTxHash; mnauth.sig = activeMasternodeInfo.blsKeyOperator->Sign(signHash); - LogPrint("net", "CMNAuth::%s -- Sending MNAUTH, peer=%d\n", __func__, pnode->id); + LogPrint(BCLog::NET, "CMNAuth::%s -- Sending MNAUTH, peer=%d\n", __func__, pnode->id); connman.PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::MNAUTH, mnauth)); } @@ -99,7 +99,7 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS connman.ForEachNode([&](CNode* pnode2) { if (pnode2->verifiedProRegTxHash == mnauth.proRegTxHash) { - LogPrint("net", "CMNAuth::ProcessMessage -- Masternode %s has already verified as peer %d, dropping old connection. peer=%d\n", + LogPrint(BCLog::NET, "CMNAuth::ProcessMessage -- Masternode %s has already verified as peer %d, dropping old connection. peer=%d\n", mnauth.proRegTxHash.ToString(), pnode2->id, pnode->id); pnode2->fDisconnect = true; } @@ -111,7 +111,7 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS pnode->verifiedPubKeyHash = dmn->pdmnState->pubKeyOperator.GetHash(); } - LogPrint("net", "CMNAuth::%s -- Valid MNAUTH for %s, peer=%d\n", __func__, mnauth.proRegTxHash.ToString(), pnode->id); + LogPrint(BCLog::NET, "CMNAuth::%s -- Valid MNAUTH for %s, peer=%d\n", __func__, mnauth.proRegTxHash.ToString(), pnode->id); } } @@ -140,7 +140,7 @@ void CMNAuth::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& } if (doRemove) { - LogPrint("net", "CMNAuth::NotifyMasternodeListChanged -- Disconnecting MN %s due to key changed/removed, peer=%d\n", + LogPrint(BCLog::NET, "CMNAuth::NotifyMasternodeListChanged -- Disconnecting MN %s due to key changed/removed, peer=%d\n", pnode->verifiedProRegTxHash.ToString(), pnode->id); pnode->fDisconnect = true; } diff --git a/src/evo/specialtx.cpp b/src/evo/specialtx.cpp index f18bcf2df7d3..dd141f968715 100644 --- a/src/evo/specialtx.cpp +++ b/src/evo/specialtx.cpp @@ -106,28 +106,28 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CV } int64_t nTime2 = GetTimeMicros(); nTimeLoop += nTime2 - nTime1; - LogPrint("bench", " - Loop: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeLoop * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Loop: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeLoop * 0.000001); if (!llmq::quorumBlockProcessor->ProcessBlock(block, pindex, state)) { return false; } int64_t nTime3 = GetTimeMicros(); nTimeQuorum += nTime3 - nTime2; - LogPrint("bench", " - quorumBlockProcessor: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeQuorum * 0.000001); + LogPrint(BCLog::BENCHMARK, " - quorumBlockProcessor: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeQuorum * 0.000001); if (!deterministicMNManager->ProcessBlock(block, pindex, state, fJustCheck)) { return false; } int64_t nTime4 = GetTimeMicros(); nTimeDMN += nTime4 - nTime3; - LogPrint("bench", " - deterministicMNManager: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeDMN * 0.000001); + LogPrint(BCLog::BENCHMARK, " - deterministicMNManager: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeDMN * 0.000001); if (fCheckCbTxMerleRoots && !CheckCbTxMerkleRoots(block, pindex, state)) { return false; } int64_t nTime5 = GetTimeMicros(); nTimeMerkle += nTime5 - nTime4; - LogPrint("bench", " - CheckCbTxMerkleRoots: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001); + LogPrint(BCLog::BENCHMARK, " - CheckCbTxMerkleRoots: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001); return true; } diff --git a/src/governance/governance-classes.cpp b/src/governance/governance-classes.cpp index d726d89594dd..0cce9518680d 100644 --- a/src/governance/governance-classes.cpp +++ b/src/governance/governance-classes.cpp @@ -100,7 +100,7 @@ bool CGovernanceTriggerManager::AddNewTrigger(uint256 nHash) // IF WE ALREADY HAVE THIS HASH, RETURN if (mapTrigger.count(nHash)) { - LogPrint("gobject", "CGovernanceTriggerManager::AddNewTrigger -- Already have hash, nHash = %s, count = %d, size = %s\n", + LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::AddNewTrigger -- Already have hash, nHash = %s, count = %d, size = %s\n", nHash.GetHex(), mapTrigger.count(nHash), mapTrigger.size()); return false; } @@ -135,7 +135,7 @@ void CGovernanceTriggerManager::CleanAndRemove() AssertLockHeld(governance.cs); // Remove triggers that are invalid or expired - LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- mapTrigger.size() = %d\n", mapTrigger.size()); + LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- mapTrigger.size() = %d\n", mapTrigger.size()); trigger_m_it it = mapTrigger.begin(); while (it != mapTrigger.end()) { @@ -143,20 +143,20 @@ void CGovernanceTriggerManager::CleanAndRemove() CGovernanceObject* pObj = nullptr; CSuperblock_sptr& pSuperblock = it->second; if (!pSuperblock) { - LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- NULL superblock marked for removal\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- NULL superblock marked for removal\n"); remove = true; } else { pObj = governance.FindGovernanceObject(it->first); if (!pObj || pObj->GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) { - LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Unknown or non-trigger superblock\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- Unknown or non-trigger superblock\n"); pSuperblock->SetStatus(SEEN_OBJECT_ERROR_INVALID); } - LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- superblock status = %d\n", pSuperblock->GetStatus()); + LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- superblock status = %d\n", pSuperblock->GetStatus()); switch (pSuperblock->GetStatus()) { case SEEN_OBJECT_ERROR_INVALID: case SEEN_OBJECT_UNKNOWN: - LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Unknown or invalid trigger found\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- Unknown or invalid trigger found\n"); remove = true; break; case SEEN_OBJECT_IS_VALID: @@ -167,14 +167,14 @@ void CGovernanceTriggerManager::CleanAndRemove() break; } } - LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- %smarked for removal\n", remove ? "" : "NOT "); + LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- %smarked for removal\n", remove ? "" : "NOT "); if (remove) { std::string strDataAsPlainString = "NULL"; if (pObj) { strDataAsPlainString = pObj->GetDataAsPlainString(); } - LogPrint("gobject", "CGovernanceTriggerManager::CleanAndRemove -- Removing trigger object %s\n", strDataAsPlainString); + LogPrint(BCLog::GOBJECT, "CGovernanceTriggerManager::CleanAndRemove -- Removing trigger object %s\n", strDataAsPlainString); // mark corresponding object for deletion if (pObj) { pObj->fCachedDelete = true; @@ -221,7 +221,7 @@ std::vector CGovernanceTriggerManager::GetActiveTriggers() bool CSuperblockManager::IsSuperblockTriggered(int nBlockHeight) { - LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- Start nBlockHeight = %d\n", nBlockHeight); + LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- Start nBlockHeight = %d\n", nBlockHeight); if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) { return false; } @@ -230,7 +230,7 @@ bool CSuperblockManager::IsSuperblockTriggered(int nBlockHeight) // GET ALL ACTIVE TRIGGERS std::vector vecTriggers = triggerman.GetActiveTriggers(); - LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- vecTriggers.size() = %d\n", vecTriggers.size()); + LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- vecTriggers.size() = %d\n", vecTriggers.size()); for (const auto& pSuperblock : vecTriggers) { if (!pSuperblock) { @@ -245,12 +245,12 @@ bool CSuperblockManager::IsSuperblockTriggered(int nBlockHeight) continue; } - LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- data = %s\n", pObj->GetDataAsPlainString()); + LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- data = %s\n", pObj->GetDataAsPlainString()); // note : 12.1 - is epoch calculation correct? if (nBlockHeight != pSuperblock->GetBlockHeight()) { - LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- block height doesn't match nBlockHeight = %d, blockStart = %d, continuing\n", + LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- block height doesn't match nBlockHeight = %d, blockStart = %d, continuing\n", nBlockHeight, pSuperblock->GetBlockHeight()); continue; @@ -261,10 +261,10 @@ bool CSuperblockManager::IsSuperblockTriggered(int nBlockHeight) pObj->UpdateSentinelVariables(); if (pObj->IsSetCachedFunding()) { - LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = true, returning true\n"); + LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = true, returning true\n"); return true; } else { - LogPrint("gobject", "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = false, continuing\n"); + LogPrint(BCLog::GOBJECT, "CSuperblockManager::IsSuperblockTriggered -- fCacheFunding = false, continuing\n"); } } @@ -319,7 +319,7 @@ bool CSuperblockManager::GetSuperblockPayments(int nBlockHeight, std::vectorGetDataAsPlainString(), pGovObj->GetObjectType()); if (pGovObj->GetObjectType() != GOVERNANCE_OBJECT_TRIGGER) { @@ -424,7 +424,7 @@ CSuperblock:: std::string strAmounts = obj["payment_amounts"].get_str(); ParsePaymentSchedule(strAddresses, strAmounts); - LogPrint("gobject", "CSuperblock -- nBlockHeight = %d, strAddresses = %s, strAmounts = %s, vecPayments.size() = %d\n", + LogPrint(BCLog::GOBJECT, "CSuperblock -- nBlockHeight = %d, strAddresses = %s, strAmounts = %s, vecPayments.size() = %d\n", nBlockHeight, strAddresses, strAmounts, vecPayments.size()); } @@ -473,7 +473,7 @@ CAmount CSuperblock::GetPaymentsLimit(int nBlockHeight) // some part of all blocks issued during the cycle goes to superblock, see GetBlockSubsidy CAmount nSuperblockPartOfSubsidy = GetBlockSubsidy(nBits, nBlockHeight - 1, consensusParams, true); CAmount nPaymentsLimit = nSuperblockPartOfSubsidy * consensusParams.nSuperblockCycle; - LogPrint("gobject", "CSuperblock::GetPaymentsLimit -- Valid superblock height %d, payments max %lld\n", nBlockHeight, nPaymentsLimit); + LogPrint(BCLog::GOBJECT, "CSuperblock::GetPaymentsLimit -- Valid superblock height %d, payments max %lld\n", nBlockHeight, nPaymentsLimit); return nPaymentsLimit; } @@ -532,7 +532,7 @@ void CSuperblock::ParsePaymentSchedule(const std::string& strPaymentAddresses, c CAmount nAmount = ParsePaymentAmount(vecParsed2[i]); - LogPrint("gobject", "CSuperblock::ParsePaymentSchedule -- i = %d, amount string = %s, nAmount = %lld\n", i, vecParsed2[i], nAmount); + LogPrint(BCLog::GOBJECT, "CSuperblock::ParsePaymentSchedule -- i = %d, amount string = %s, nAmount = %lld\n", i, vecParsed2[i], nAmount); CGovernancePayment payment(address, nAmount); if (payment.IsValid()) { @@ -596,7 +596,7 @@ bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount b int nPayments = CountPayments(); int nMinerAndMasternodePayments = nOutputs - nPayments; - LogPrint("gobject", "CSuperblock::IsValid -- nOutputs = %d, nPayments = %d, GetDataAsHexString = %s\n", + LogPrint(BCLog::GOBJECT, "CSuperblock::IsValid -- nOutputs = %d, nPayments = %d, GetDataAsHexString = %s\n", nOutputs, nPayments, GetGovernanceObject()->GetDataAsHexString()); // We require an exact match (including order) between the expected @@ -682,14 +682,14 @@ bool CSuperblock::IsExpired() int nExpirationBlock = nBlockHeight + nExpirationBlocks; - LogPrint("gobject", "CSuperblock::IsExpired -- nBlockHeight = %d, nExpirationBlock = %d\n", nBlockHeight, nExpirationBlock); + LogPrint(BCLog::GOBJECT, "CSuperblock::IsExpired -- nBlockHeight = %d, nExpirationBlock = %d\n", nBlockHeight, nExpirationBlock); if (governance.GetCachedBlockHeight() > nExpirationBlock) { - LogPrint("gobject", "CSuperblock::IsExpired -- Outdated trigger found\n"); + LogPrint(BCLog::GOBJECT, "CSuperblock::IsExpired -- Outdated trigger found\n"); fExpired = true; CGovernanceObject* pgovobj = GetGovernanceObject(); if (pgovobj) { - LogPrint("gobject", "CSuperblock::IsExpired -- Expiring outdated object: %s\n", pgovobj->GetHash().ToString()); + LogPrint(BCLog::GOBJECT, "CSuperblock::IsExpired -- Expiring outdated object: %s\n", pgovobj->GetHash().ToString()); pgovobj->fExpired = true; pgovobj->nDeletionTime = GetAdjustedTime(); } @@ -713,7 +713,7 @@ std::string CSuperblockManager::GetRequiredPaymentsString(int nBlockHeight) CSuperblock_sptr pSuperblock; if (!GetBestSuperblock(pSuperblock, nBlockHeight)) { - LogPrint("gobject", "CSuperblockManager::GetRequiredPaymentsString -- Can't find superblock for height %d\n", nBlockHeight); + LogPrint(BCLog::GOBJECT, "CSuperblockManager::GetRequiredPaymentsString -- Can't find superblock for height %d\n", nBlockHeight); return "error"; } diff --git a/src/governance/governance-object.cpp b/src/governance/governance-object.cpp index e539c18d5ded..69b95352e991 100644 --- a/src/governance/governance-object.cpp +++ b/src/governance/governance-object.cpp @@ -115,7 +115,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, // nothing to do here, not an error std::ostringstream ostr; ostr << "CGovernanceObject::ProcessVote -- Already known valid vote"; - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_NONE); return false; } @@ -130,7 +130,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, if (cmmapOrphanVotes.Insert(vote.GetMasternodeOutpoint(), vote_time_pair_t(vote, GetAdjustedTime() + GOVERNANCE_ORPHAN_EXPIRATION_TIME))) { LogPrintf("%s\n", ostr.str()); } else { - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); } return false; } @@ -141,7 +141,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, if (eSignal == VOTE_SIGNAL_NONE) { std::ostringstream ostr; ostr << "CGovernanceObject::ProcessVote -- Vote signal: none"; - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_WARNING); return false; } @@ -159,7 +159,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, if (vote.GetTimestamp() < voteInstanceRef.nCreationTime) { std::ostringstream ostr; ostr << "CGovernanceObject::ProcessVote -- Obsolete vote"; - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_NONE); return false; } else if (vote.GetTimestamp() == voteInstanceRef.nCreationTime) { @@ -171,12 +171,12 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, // This is an arbitrary comparison, we have to agree on some way // to pick the "winning" vote. ostr << ", rejected"; - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_NONE); return false; } ostr << ", accepted"; - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); } int64_t nNow = GetAdjustedTime(); @@ -189,7 +189,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, << ", MN outpoint = " << vote.GetMasternodeOutpoint().ToStringShort() << ", governance object hash = " << GetHash().ToString() << ", time delta = " << nTimeDelta; - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_TEMPORARY_ERROR); return false; } @@ -216,7 +216,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, ostr << "CGovernanceObject::ProcessVote -- Unable to add governance vote" << ", MN outpoint = " << vote.GetMasternodeOutpoint().ToStringShort() << ", governance object hash = " << GetHash().ToString(); - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); exception = CGovernanceException(ostr.str(), GOVERNANCE_EXCEPTION_PERMANENT_ERROR); return false; } @@ -391,7 +391,7 @@ void CGovernanceObject::LoadData() // ATTEMPT TO LOAD JSON STRING FROM VCHDATA UniValue objResult(UniValue::VOBJ); GetData(objResult); - LogPrint("gobject", "CGovernanceObject::LoadData -- GetDataAsPlainString = %s\n", GetDataAsPlainString()); + LogPrint(BCLog::GOBJECT, "CGovernanceObject::LoadData -- GetDataAsPlainString = %s\n", GetDataAsPlainString()); UniValue obj = GetJSONObject(); nObjectType = obj["type"].get_int(); } catch (std::exception& e) { @@ -570,12 +570,12 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC CScript findScript; findScript << OP_RETURN << ToByteVector(nExpectedHash); - LogPrint("gobject", "CGovernanceObject::IsCollateralValid -- txCollateral->vout.size() = %s, findScript = %s, nMinFee = %lld\n", + LogPrint(BCLog::GOBJECT, "CGovernanceObject::IsCollateralValid -- txCollateral->vout.size() = %s, findScript = %s, nMinFee = %lld\n", txCollateral->vout.size(), ScriptToAsmStr(findScript, false), nMinFee); bool foundOpReturn = false; for (const auto& output : txCollateral->vout) { - LogPrint("gobject", "CGovernanceObject::IsCollateralValid -- txout = %s, output.nValue = %lld, output.scriptPubKey = %s\n", + LogPrint(BCLog::GOBJECT, "CGovernanceObject::IsCollateralValid -- txout = %s, output.nValue = %lld, output.scriptPubKey = %s\n", output.ToString(), output.nValue, ScriptToAsmStr(output.scriptPubKey, false)); if (!output.scriptPubKey.IsPayToPublicKeyHash() && !output.scriptPubKey.IsUnspendable()) { strError = strprintf("Invalid Script %s", txCollateral->ToString()); @@ -685,7 +685,7 @@ void CGovernanceObject::Relay(CConnman& connman) { // Do not relay until fully synced if (!masternodeSync.IsSynced()) { - LogPrint("gobject", "CGovernanceObject::Relay -- won't relay until fully synced\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceObject::Relay -- won't relay until fully synced\n"); return; } diff --git a/src/governance/governance-object.h b/src/governance/governance-object.h index 87a24dd76c07..30d7a66aec85 100644 --- a/src/governance/governance-object.h +++ b/src/governance/governance-object.h @@ -320,12 +320,12 @@ class CGovernanceObject } if (s.GetType() & SER_DISK) { // Only include these for the disk file format - LogPrint("gobject", "CGovernanceObject::SerializationOp Reading/writing votes from/to disk\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceObject::SerializationOp Reading/writing votes from/to disk\n"); READWRITE(nDeletionTime); READWRITE(fExpired); READWRITE(mapCurrentMNVotes); READWRITE(fileVotes); - LogPrint("gobject", "CGovernanceObject::SerializationOp hash = %s, vote count = %d\n", GetHash().ToString(), fileVotes.GetVoteCount()); + LogPrint(BCLog::GOBJECT, "CGovernanceObject::SerializationOp hash = %s, vote count = %d\n", GetHash().ToString(), fileVotes.GetVoteCount()); } // AFTER DESERIALIZATION OCCURS, CACHED VARIABLES MUST BE CALCULATED MANUALLY diff --git a/src/governance/governance-vote.cpp b/src/governance/governance-vote.cpp index 81555fb9d6b6..53816bc8a30e 100644 --- a/src/governance/governance-vote.cpp +++ b/src/governance/governance-vote.cpp @@ -116,7 +116,7 @@ void CGovernanceVote::Relay(CConnman& connman) const { // Do not relay until fully synced if (!masternodeSync.IsSynced()) { - LogPrint("gobject", "CGovernanceVote::Relay -- won't relay until fully synced\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceVote::Relay -- won't relay until fully synced\n"); return; } @@ -197,7 +197,7 @@ bool CGovernanceVote::CheckSignature(const CKeyID& keyID) const if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) { // nope, not in old format either - LogPrint("gobject", "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError); + LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError); return false; } } @@ -208,7 +208,7 @@ bool CGovernanceVote::CheckSignature(const CKeyID& keyID) const std::to_string(nTime); if (!CMessageSigner::VerifyMessage(keyID, vchSig, strMessage, strError)) { - LogPrint("gobject", "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError); + LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s\n", strError); return false; } } @@ -242,25 +242,25 @@ bool CGovernanceVote::CheckSignature(const CBLSPublicKey& pubKey) const bool CGovernanceVote::IsValid(bool useVotingKey) const { if (nTime > GetAdjustedTime() + (60 * 60)) { - LogPrint("gobject", "CGovernanceVote::IsValid -- vote is too far ahead of current time - %s - nTime %lli - Max Time %lli\n", GetHash().ToString(), nTime, GetAdjustedTime() + (60 * 60)); + LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- vote is too far ahead of current time - %s - nTime %lli - Max Time %lli\n", GetHash().ToString(), nTime, GetAdjustedTime() + (60 * 60)); return false; } // support up to MAX_SUPPORTED_VOTE_SIGNAL, can be extended if (nVoteSignal > MAX_SUPPORTED_VOTE_SIGNAL) { - LogPrint("gobject", "CGovernanceVote::IsValid -- Client attempted to vote on invalid signal(%d) - %s\n", nVoteSignal, GetHash().ToString()); + LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Client attempted to vote on invalid signal(%d) - %s\n", nVoteSignal, GetHash().ToString()); return false; } // 0=none, 1=yes, 2=no, 3=abstain. Beyond that reject votes if (nVoteOutcome > 3) { - LogPrint("gobject", "CGovernanceVote::IsValid -- Client attempted to vote on invalid outcome(%d) - %s\n", nVoteSignal, GetHash().ToString()); + LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Client attempted to vote on invalid outcome(%d) - %s\n", nVoteSignal, GetHash().ToString()); return false; } auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(masternodeOutpoint); if (!dmn) { - LogPrint("gobject", "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", masternodeOutpoint.ToStringShort()); + LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", masternodeOutpoint.ToStringShort()); return false; } diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index 6dcadfa4f1df..b5cb586c228a 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -95,7 +95,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm // ANOTHER USER IS ASKING US TO HELP THEM SYNC GOVERNANCE OBJECT DATA if (strCommand == NetMsgType::MNGOVERNANCESYNC) { if (pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) { - LogPrint("gobject", "MNGOVERNANCESYNC -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCESYNC -- 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", MIN_GOVERNANCE_PEER_PROTO_VERSION))); return; } @@ -122,7 +122,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm } else { SyncSingleObjVotes(pfrom, nProp, filter, connman); } - LogPrint("gobject", "MNGOVERNANCESYNC -- syncing governance objects to our peer at %s\n", pfrom->addr.ToString()); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCESYNC -- syncing governance objects to our peer at %s\n", pfrom->addr.ToString()); } // A NEW GOVERNANCE OBJECT HAS ARRIVED @@ -140,19 +140,19 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm } if (pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) { - LogPrint("gobject", "MNGOVERNANCEOBJECT -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- 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", MIN_GOVERNANCE_PEER_PROTO_VERSION))); return; } if (!masternodeSync.IsBlockchainSynced()) { - LogPrint("gobject", "MNGOVERNANCEOBJECT -- masternode list not synced\n"); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- masternode list not synced\n"); return; } std::string strHash = nHash.ToString(); - LogPrint("gobject", "MNGOVERNANCEOBJECT -- Received object: %s\n", strHash); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Received object: %s\n", strHash); if (!AcceptObjectMessage(nHash)) { LogPrintf("MNGOVERNANCEOBJECT -- Received unrequested object: %s\n", strHash); @@ -164,7 +164,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm if (mapObjects.count(nHash) || mapPostponedObjects.count(nHash) || mapErasedGovernanceObjects.count(nHash) || mapMasternodeOrphanObjects.count(nHash)) { // TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE? - LogPrint("gobject", "MNGOVERNANCEOBJECT -- Received already seen object: %s\n", strHash); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Received already seen object: %s\n", strHash); return; } @@ -192,7 +192,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm if (fMasternodeMissing) { int& count = mapMasternodeOrphanCounter[govobj.GetMasternodeOutpoint()]; if (count >= 10) { - LogPrint("gobject", "MNGOVERNANCEOBJECT -- Too many orphan objects, missing masternode=%s\n", govobj.GetMasternodeOutpoint().ToStringShort()); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Too many orphan objects, missing masternode=%s\n", govobj.GetMasternodeOutpoint().ToStringShort()); // ask for this object again in 2 minutes CInv inv(MSG_GOVERNANCE_OBJECT, govobj.GetHash()); pfrom->AskFor(inv); @@ -231,33 +231,33 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm } if (pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) { - LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- 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", MIN_GOVERNANCE_PEER_PROTO_VERSION))); } // Ignore such messages until masternode list is synced if (!masternodeSync.IsBlockchainSynced()) { - LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- masternode list not synced\n"); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- masternode list not synced\n"); return; } - LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- Received vote: %s\n", vote.ToString()); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- Received vote: %s\n", vote.ToString()); std::string strHash = nHash.ToString(); if (!AcceptVoteMessage(nHash)) { - LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- Received unrequested vote object: %s, hash: %s, peer = %d\n", + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- Received unrequested vote object: %s, hash: %s, peer = %d\n", vote.ToString(), strHash, pfrom->GetId()); return; } CGovernanceException exception; if (ProcessVote(pfrom, vote, exception, connman)) { - LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- %s new\n", strHash); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- %s new\n", strHash); masternodeSync.BumpAssetLastTime("MNGOVERNANCEOBJECTVOTE"); vote.Relay(connman); } else { - LogPrint("gobject", "MNGOVERNANCEOBJECTVOTE -- Rejected vote, error = %s\n", exception.what()); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- Rejected vote, error = %s\n", exception.what()); if ((exception.GetNodePenalty() != 0) && masternodeSync.IsSynced()) { LOCK(cs_main); Misbehaving(pfrom->GetId(), exception.GetNodePenalty()); @@ -313,7 +313,7 @@ void CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CConnman return; } - LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- Adding object: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType()); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- Adding object: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType()); // INSERT INTO OUR GOVERNANCE OBJECT MEMORY // IF WE HAVE THIS OBJECT ALREADY, WE DON'T WANT ANOTHER COPY @@ -326,12 +326,12 @@ void CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CConnman // SHOULD WE ADD THIS OBJECT TO ANY OTHER MANANGERS? - LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- Before trigger block, GetDataAsPlainString = %s, nObjectType = %d\n", + LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- Before trigger block, GetDataAsPlainString = %s, nObjectType = %d\n", govobj.GetDataAsPlainString(), govobj.nObjectType); if (govobj.nObjectType == GOVERNANCE_OBJECT_TRIGGER) { if (!triggerman.AddNewTrigger(nHash)) { - LogPrint("gobject", "CGovernanceManager::AddGovernanceObject -- undo adding invalid trigger object: hash = %s\n", nHash.ToString()); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::AddGovernanceObject -- undo adding invalid trigger object: hash = %s\n", nHash.ToString()); CGovernanceObject& objref = objpair.first->second; objref.fCachedDelete = true; if (objref.nDeletionTime == 0) { @@ -360,7 +360,7 @@ void CGovernanceManager::AddGovernanceObject(CGovernanceObject& govobj, CConnman void CGovernanceManager::UpdateCachesAndClean() { - LogPrint("gobject", "CGovernanceManager::UpdateCachesAndClean\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::UpdateCachesAndClean\n"); std::vector vecDirtyHashes = mmetaman.GetAndClearDirtyGovernanceObjectHashes(); @@ -407,7 +407,7 @@ void CGovernanceManager::UpdateCachesAndClean() int64_t nTimeSinceDeletion = nNow - pObj->GetDeletionTime(); - LogPrint("gobject", "CGovernanceManager::UpdateCachesAndClean -- Checking object for deletion: %s, deletion time = %d, time since deletion = %d, delete flag = %d, expired flag = %d\n", + LogPrint(BCLog::GOBJECT, "CGovernanceManager::UpdateCachesAndClean -- Checking object for deletion: %s, deletion time = %d, time since deletion = %d, delete flag = %d, expired flag = %d\n", strHash, pObj->GetDeletionTime(), nTimeSinceDeletion, pObj->IsSetCachedDelete(), pObj->IsSetExpired()); if ((pObj->IsSetCachedDelete() || pObj->IsSetExpired()) && @@ -575,26 +575,26 @@ bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv) LOCK(cs); - LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest inv = %s\n", inv.ToString()); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::ConfirmInventoryRequest inv = %s\n", inv.ToString()); // First check if we've already recorded this object switch (inv.type) { case MSG_GOVERNANCE_OBJECT: { if (mapObjects.count(inv.hash) == 1 || mapPostponedObjects.count(inv.hash) == 1) { - LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest already have governance object, returning false\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::ConfirmInventoryRequest already have governance object, returning false\n"); return false; } break; } case MSG_GOVERNANCE_OBJECT_VOTE: { if (cmapVoteToObject.HasKey(inv.hash)) { - LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest already have governance vote, returning false\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::ConfirmInventoryRequest already have governance vote, returning false\n"); return false; } break; } default: - LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest unknown type, returning false\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::ConfirmInventoryRequest unknown type, returning false\n"); return false; } @@ -614,10 +614,10 @@ bool CGovernanceManager::ConfirmInventoryRequest(const CInv& inv) hash_s_cit it = setHash->find(inv.hash); if (it == setHash->end()) { setHash->insert(inv.hash); - LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest added inv to requested set\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::ConfirmInventoryRequest added inv to requested set\n"); } - LogPrint("gobject", "CGovernanceManager::ConfirmInventoryRequest reached end, returning true\n"); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::ConfirmInventoryRequest reached end, returning true\n"); return true; } @@ -630,20 +630,20 @@ void CGovernanceManager::SyncSingleObjVotes(CNode* pnode, const uint256& nProp, // SYNC GOVERNANCE OBJECTS WITH OTHER CLIENT - LogPrint("gobject", "CGovernanceManager::%s -- syncing single object to peer=%d, nProp = %s\n", __func__, pnode->id, nProp.ToString()); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing single object to peer=%d, nProp = %s\n", __func__, pnode->id, nProp.ToString()); LOCK2(cs_main, cs); // single valid object and its valid votes object_m_it it = mapObjects.find(nProp); if (it == mapObjects.end()) { - LogPrint("gobject", "CGovernanceManager::%s -- no matching object for hash %s, peer=%d\n", __func__, nProp.ToString(), pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- no matching object for hash %s, peer=%d\n", __func__, nProp.ToString(), pnode->id); return; } CGovernanceObject& govobj = it->second; std::string strHash = it->first.ToString(); - LogPrint("gobject", "CGovernanceManager::%s -- attempting to sync govobj: %s, peer=%d\n", __func__, strHash, pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- attempting to sync govobj: %s, peer=%d\n", __func__, strHash, pnode->id); if (govobj.IsSetCachedDelete() || govobj.IsSetExpired()) { LogPrintf("CGovernanceManager::%s -- not syncing deleted/expired govobj: %s, peer=%d\n", __func__, @@ -678,7 +678,7 @@ void CGovernanceManager::SyncObjects(CNode* pnode, CConnman& connman) const if (netfulfilledman.HasFulfilledRequest(pnode->addr, NetMsgType::MNGOVERNANCESYNC)) { LOCK(cs_main); // Asking for the whole list multiple times in a short period of time is no good - LogPrint("gobject", "CGovernanceManager::%s -- peer already asked me for the list\n", __func__); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- peer already asked me for the list\n", __func__); Misbehaving(pnode->GetId(), 20); return; } @@ -688,7 +688,7 @@ void CGovernanceManager::SyncObjects(CNode* pnode, CConnman& connman) const // SYNC GOVERNANCE OBJECTS WITH OTHER CLIENT - LogPrint("gobject", "CGovernanceManager::%s -- syncing all objects to peer=%d\n", __func__, pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing all objects to peer=%d\n", __func__, pnode->id); LOCK2(cs_main, cs); @@ -698,7 +698,7 @@ void CGovernanceManager::SyncObjects(CNode* pnode, CConnman& connman) const const CGovernanceObject& govobj = objPair.second; std::string strHash = nHash.ToString(); - LogPrint("gobject", "CGovernanceManager::%s -- attempting to sync govobj: %s, peer=%d\n", __func__, strHash, pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- attempting to sync govobj: %s, peer=%d\n", __func__, strHash, pnode->id); if (govobj.IsSetCachedDelete() || govobj.IsSetExpired()) { LogPrintf("CGovernanceManager::%s -- not syncing deleted/expired govobj: %s, peer=%d\n", __func__, @@ -707,7 +707,7 @@ void CGovernanceManager::SyncObjects(CNode* pnode, CConnman& connman) const } // Push the inventory budget proposal message over to the other client - LogPrint("gobject", "CGovernanceManager::%s -- syncing govobj: %s, peer=%d\n", __func__, strHash, pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing govobj: %s, peer=%d\n", __func__, strHash, pnode->id); pnode->PushInventory(CInv(MSG_GOVERNANCE_OBJECT, nHash)); ++nObjCount; } @@ -816,7 +816,7 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote, uint256 nHashGovobj = vote.GetParentHash(); if (cmapVoteToObject.HasKey(nHashVote)) { - LogPrint("gobject", "CGovernanceObject::ProcessVote -- skipping known valid vote %s for object %s\n", nHashVote.ToString(), nHashGovobj.ToString()); + LogPrint(BCLog::GOBJECT, "CGovernanceObject::ProcessVote -- skipping known valid vote %s for object %s\n", nHashVote.ToString(), nHashGovobj.ToString()); LEAVE_CRITICAL_SECTION(cs); return false; } @@ -845,7 +845,7 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote, return false; } - LogPrint("gobject", "%s\n", ostr.str()); + LogPrint(BCLog::GOBJECT, "%s\n", ostr.str()); LEAVE_CRITICAL_SECTION(cs); return false; } @@ -853,7 +853,7 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote, CGovernanceObject& govobj = it->second; if (govobj.IsSetCachedDelete() || govobj.IsSetExpired()) { - LogPrint("gobject", "CGovernanceObject::ProcessVote -- ignoring vote for expired or deleted object, hash = %s\n", nHashGovobj.ToString()); + LogPrint(BCLog::GOBJECT, "CGovernanceObject::ProcessVote -- ignoring vote for expired or deleted object, hash = %s\n", nHashGovobj.ToString()); LEAVE_CRITICAL_SECTION(cs); return false; } @@ -980,7 +980,7 @@ void CGovernanceManager::RequestGovernanceObject(CNode* pfrom, const uint256& nH return; } - LogPrint("gobject", "CGovernanceManager::RequestGovernanceObject -- nHash %s peer=%d\n", nHash.ToString(), pfrom->GetId()); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::RequestGovernanceObject -- nHash %s peer=%d\n", nHash.ToString(), pfrom->GetId()); CNetMsgMaker msgMaker(pfrom->GetSendVersion()); @@ -1007,7 +1007,7 @@ void CGovernanceManager::RequestGovernanceObject(CNode* pfrom, const uint256& nH } } - LogPrint("gobject", "CGovernanceManager::RequestGovernanceObject -- nHash %s nVoteCount %d peer=%d\n", nHash.ToString(), nVoteCount, pfrom->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::RequestGovernanceObject -- nHash %s nVoteCount %d peer=%d\n", nHash.ToString(), nVoteCount, pfrom->id); connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNGOVERNANCESYNC, nHash, filter)); } @@ -1070,7 +1070,7 @@ int CGovernanceManager::RequestGovernanceObjectVotes(const std::vector& } } - LogPrint("gobject", "CGovernanceManager::RequestGovernanceObjectVotes -- start: vTriggerObjHashes %d vOtherObjHashes %d mapAskedRecently %d\n", + LogPrint(BCLog::GOBJECT, "CGovernanceManager::RequestGovernanceObjectVotes -- start: vTriggerObjHashes %d vOtherObjHashes %d mapAskedRecently %d\n", vTriggerObjHashes.size(), vOtherObjHashes.size(), mapAskedRecently.size()); FastRandomContext insecure_rand; @@ -1119,7 +1119,7 @@ int CGovernanceManager::RequestGovernanceObjectVotes(const std::vector& } if (!fAsked) i--; } - LogPrint("gobject", "CGovernanceManager::RequestGovernanceObjectVotes -- end: vTriggerObjHashes %d vOtherObjHashes %d mapAskedRecently %d\n", + LogPrint(BCLog::GOBJECT, "CGovernanceManager::RequestGovernanceObjectVotes -- end: vTriggerObjHashes %d vOtherObjHashes %d mapAskedRecently %d\n", vTriggerObjHashes.size(), vOtherObjHashes.size(), mapAskedRecently.size()); return int(vTriggerObjHashes.size() + vOtherObjHashes.size()); @@ -1266,7 +1266,7 @@ void CGovernanceManager::UpdatedBlockTip(const CBlockIndex* pindex, CConnman& co } nCachedBlockHeight = pindex->nHeight; - LogPrint("gobject", "CGovernanceManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight); if (deterministicMNManager->IsDIP3Enforced(pindex->nHeight)) { RemoveInvalidVotes(); @@ -1293,7 +1293,7 @@ void CGovernanceManager::RequestOrphanObjects(CConnman& connman) } } - LogPrint("gobject", "CGovernanceObject::RequestOrphanObjects -- number objects = %d\n", vecHashesFiltered.size()); + LogPrint(BCLog::GOBJECT, "CGovernanceObject::RequestOrphanObjects -- number objects = %d\n", vecHashesFiltered.size()); for (const uint256& nHash : vecHashesFiltered) { for (CNode* pnode : vNodesCopy) { if (pnode->fMasternode) { diff --git a/src/governance/governance.h b/src/governance/governance.h index 466b0f971013..e30a51b5cb02 100644 --- a/src/governance/governance.h +++ b/src/governance/governance.h @@ -322,7 +322,7 @@ class CGovernanceManager { LOCK(cs); - LogPrint("gobject", "Governance object manager was cleared\n"); + LogPrint(BCLog::GOBJECT, "Governance object manager was cleared\n"); mapObjects.clear(); mapErasedGovernanceObjects.clear(); cmapVoteToObject.Clear(); diff --git a/src/httprpc.cpp b/src/httprpc.cpp index bd59cc1a62e4..c7241bf4dbbc 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -233,7 +233,7 @@ static bool InitRPCAuthentication() bool StartHTTPRPC() { - LogPrint("rpc", "Starting HTTP RPC server\n"); + LogPrint(BCLog::RPC, "Starting HTTP RPC server\n"); if (!InitRPCAuthentication()) return false; @@ -247,12 +247,12 @@ bool StartHTTPRPC() void InterruptHTTPRPC() { - LogPrint("rpc", "Interrupting HTTP RPC server\n"); + LogPrint(BCLog::RPC, "Interrupting HTTP RPC server\n"); } void StopHTTPRPC() { - LogPrint("rpc", "Stopping HTTP RPC server\n"); + LogPrint(BCLog::RPC, "Stopping HTTP RPC server\n"); UnregisterHTTPHandler("/", true); if (httpRPCTimerInterface) { RPCUnsetTimerInterface(httpRPCTimerInterface); diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 21b3bd090403..80da394fe6a0 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -214,7 +214,7 @@ static bool InitHTTPAllowList() std::string strAllowed; for (const CSubNet& subnet : rpc_allow_subnets) strAllowed += subnet.ToString() + " "; - LogPrint("http", "Allowing HTTP connections from: %s\n", strAllowed); + LogPrint(BCLog::HTTP, "Allowing HTTP connections from: %s\n", strAllowed); return true; } @@ -244,7 +244,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg) { std::unique_ptr hreq(new HTTPRequest(req)); - LogPrint("http", "Received a %s request for %s from %s\n", + LogPrint(BCLog::HTTP, "Received a %s request for %s from %s\n", RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString()); // Early address-based allow check @@ -294,7 +294,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg) /** Callback to reject HTTP requests after shutdown. */ static void http_reject_request_cb(struct evhttp_request* req, void*) { - LogPrint("http", "Rejecting request while shutting down\n"); + LogPrint(BCLog::HTTP, "Rejecting request while shutting down\n"); evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL); } @@ -302,10 +302,10 @@ static void http_reject_request_cb(struct evhttp_request* req, void*) static bool ThreadHTTP(struct event_base* base, struct evhttp* http) { RenameThread("dash-http"); - LogPrint("http", "Entering http event loop\n"); + LogPrint(BCLog::HTTP, "Entering http event loop\n"); event_base_dispatch(base); // Event loop will be interrupted by InterruptHTTPServer() - LogPrint("http", "Exited http event loop\n"); + LogPrint(BCLog::HTTP, "Exited http event loop\n"); return event_base_got_break(base) == 0; } @@ -337,7 +337,7 @@ static bool HTTPBindAddresses(struct evhttp* http) // Bind addresses for (std::vector >::iterator i = endpoints.begin(); i != endpoints.end(); ++i) { - LogPrint("http", "Binding RPC on address %s port %i\n", i->first, i->second); + LogPrint(BCLog::HTTP, "Binding RPC on address %s port %i\n", i->first, i->second); evhttp_bound_socket *bind_handle = evhttp_bind_socket_with_handle(http, i->first.empty() ? NULL : i->first.c_str(), i->second); if (bind_handle) { boundSockets.push_back(bind_handle); @@ -366,7 +366,7 @@ static void libevent_log_cb(int severity, const char *msg) LogPrintf("libevent: %s\n", msg); // The below code causes log spam on Travis and the output of these logs has never been of any use so far //else - // LogPrint("libevent", "libevent: %s\n", msg); + // LogPrint(BCLog::LIBEVENT, "libevent: %s\n", msg); } bool InitHTTPServer() @@ -389,10 +389,11 @@ bool InitHTTPServer() #if LIBEVENT_VERSION_NUMBER >= 0x02010100 // If -debug=libevent, set full libevent debugging. // Otherwise, disable all libevent debugging. - if (LogAcceptCategory("libevent")) + if (LogAcceptCategory(BCLog::LIBEVENT)) { event_enable_debug_logging(EVENT_DBG_ALL); - else + } else { event_enable_debug_logging(EVENT_DBG_NONE); + } #endif #ifdef WIN32 evthread_use_windows_threads(); @@ -426,7 +427,7 @@ bool InitHTTPServer() return false; } - LogPrint("http", "Initialized HTTP server\n"); + LogPrint(BCLog::HTTP, "Initialized HTTP server\n"); int workQueueDepth = std::max((long)GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L); LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth); @@ -441,7 +442,7 @@ std::future threadResult; bool StartHTTPServer() { - LogPrint("http", "Starting HTTP server\n"); + LogPrint(BCLog::HTTP, "Starting HTTP server\n"); int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L); LogPrintf("HTTP: starting %d worker threads\n", rpcThreads); std::packaged_task task(ThreadHTTP); @@ -457,7 +458,7 @@ bool StartHTTPServer() void InterruptHTTPServer() { - LogPrint("http", "Interrupting HTTP server\n"); + LogPrint(BCLog::HTTP, "Interrupting HTTP server\n"); if (eventHTTP) { // Unlisten sockets for (evhttp_bound_socket *socket : boundSockets) { @@ -472,20 +473,20 @@ void InterruptHTTPServer() void StopHTTPServer() { - LogPrint("http", "Stopping HTTP server\n"); + LogPrint(BCLog::HTTP, "Stopping HTTP server\n"); if (workQueue) { - LogPrint("http", "Waiting for HTTP worker threads to exit\n"); + LogPrint(BCLog::HTTP, "Waiting for HTTP worker threads to exit\n"); #ifndef WIN32 // ToDo: Disabling WaitExit() for Windows platforms is an ugly workaround for the wallet not // closing during a repair-restart. It doesn't hurt, though, because threadHTTP.timed_join // below takes care of this and sends a loopbreak. workQueue->WaitExit(); -#endif +#endif delete workQueue; workQueue = nullptr; } if (eventBase) { - LogPrint("http", "Waiting for HTTP event thread to exit\n"); + LogPrint(BCLog::HTTP, "Waiting for HTTP event thread to exit\n"); // Give event loop a few seconds to exit (to send back last RPC responses), then break it // Before this was solved with event_base_loopexit, but that didn't work as expected in // at least libevent 2.0.21 and always introduced a delay. In libevent @@ -506,7 +507,7 @@ void StopHTTPServer() event_base_free(eventBase); eventBase = 0; } - LogPrint("http", "Stopped HTTP server\n"); + LogPrint(BCLog::HTTP, "Stopped HTTP server\n"); } struct event_base* EventBase() @@ -653,7 +654,7 @@ HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod() void RegisterHTTPHandler(const std::string &prefix, bool exactMatch, const HTTPRequestHandler &handler) { - LogPrint("http", "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch); + LogPrint(BCLog::HTTP, "Registering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch); pathHandlers.push_back(HTTPPathHandler(prefix, exactMatch, handler)); } @@ -666,7 +667,7 @@ void UnregisterHTTPHandler(const std::string &prefix, bool exactMatch) break; if (i != iend) { - LogPrint("http", "Unregistering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch); + LogPrint(BCLog::HTTP, "Unregistering HTTP handler for %s (exactmatch %d)\n", prefix, exactMatch); pathHandlers.erase(i); } } diff --git a/src/init.cpp b/src/init.cpp index 938a2db9d3d3..292258d1133d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -421,7 +421,7 @@ void OnRPCStopped() uiInterface.NotifyBlockTip.disconnect(&RPCNotifyBlockChange); RPCNotifyBlockChange(false, nullptr); cvBlockChange.notify_all(); - LogPrint("rpc", "RPC stopped.\n"); + LogPrint(BCLog::RPC, "RPC stopped.\n"); } void OnRPCPreCommand(const CRPCCommand& cmd) @@ -563,12 +563,9 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-bip9params=::(::)", "Use given start/end times for specified BIP9 deployment (regtest-only). Specifying window and threshold is optional."); strUsage += HelpMessageOpt("-watchquorums=", strprintf("Watch and validate quorum communication (default: %u)", llmq::DEFAULT_WATCH_QUORUMS)); } - std::string debugCategories = "addrman, alert, bench, cmpctblock, coindb, db, http, leveldb, libevent, lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, selectcoins, tor, zmq, " - "dash (or specifically: chainlocks, gobject, instantsend, keepass, llmq, llmq-dkg, llmq-sigs, masternode, mnpayments, mnsync, privatesend, spork)"; // Don't translate these and qt below - if (mode == HMM_BITCOIN_QT) - debugCategories += ", qt"; strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + - _("If is not supplied or if = 1, output all debugging information.") + _(" can be:") + " " + debugCategories + "."); + _("If is not supplied or if = 1, output all debugging information.") + " " + _(" can be:") + " " + ListLogCategories() + "."); + strUsage += HelpMessageOpt("-debugexclude=", strprintf(_("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."))); if (showDebug) strUsage += HelpMessageOpt("-nodebug", "Turn off debugging messages, same as -debug=0"); strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)")); @@ -1138,12 +1135,31 @@ bool AppInitParameterInteraction() // ********************************************************* Step 3: parameter-to-internal-flags - fDebug = mapMultiArgs.count("-debug"); - // Special-case: if -debug=0/-nodebug is set, turn off debugging messages - if (fDebug) { + if (mapMultiArgs.count("-debug") > 0) { + // Special-case: if -debug=0/-nodebug is set, turn off debugging messages const std::vector& categories = mapMultiArgs.at("-debug"); - if (GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), std::string("0")) != categories.end()) - fDebug = false; + + if (!(GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), std::string("0")) != categories.end())) { + for (const auto& cat : categories) { + uint64_t flag; + if (!GetLogCategory(&flag, &cat)) { + InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat)); + } + logCategories |= flag; + } + } + } + + // Now remove the logging categories which were explicitly excluded + if (mapMultiArgs.count("-debugexclude") > 0) { + const std::vector& excludedCategories = mapMultiArgs.at("-debugexclude"); + for (const auto& cat : excludedCategories) { + uint64_t flag; + if (!GetLogCategory(&flag, &cat)) { + InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat)); + } + logCategories &= ~flag; + } } // Check for -debugnet @@ -1472,7 +1488,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) #ifndef WIN32 CreatePidFile(GetPidFile(), getpid()); #endif - if (GetBoolArg("-shrinkdebugfile", !fDebug)) { + if (GetBoolArg("-shrinkdebugfile", logCategories == BCLog::NONE)) { // Do this first since it both loads a bunch of debug.log into memory, // and because this needs to happen before any other debug.log printing ShrinkDebugFile(); @@ -1868,7 +1884,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) break; } } catch (const std::exception& e) { - if (fDebug) LogPrintf("%s\n", e.what()); + LogPrintf("%s\n", e.what()); strLoadError = _("Error opening block database"); break; } diff --git a/src/instantsend.cpp b/src/instantsend.cpp index 85b4cadc339a..c63614084d6d 100644 --- a/src/instantsend.cpp +++ b/src/instantsend.cpp @@ -63,7 +63,7 @@ void CInstantSend::ProcessMessage(CNode* pfrom, const std::string& strCommand, C if (strCommand == NetMsgType::TXLOCKVOTE) { // InstantSend Transaction Lock Consensus Votes if(pfrom->nVersion < MIN_INSTANTSEND_PROTO_VERSION) { - LogPrint("instantsend", "TXLOCKVOTE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::INSTANTSEND, "TXLOCKVOTE -- 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", MIN_INSTANTSEND_PROTO_VERSION))); return; @@ -122,7 +122,7 @@ bool CInstantSend::ProcessTxLockRequest(const CTxLockRequest& txLockRequest, CCo if (it != mapVotedOutpoints.end()) { for (const auto& hash : it->second) { if (hash != txLockRequest.GetHash()) { - LogPrint("instantsend", "CInstantSend::ProcessTxLockRequest -- Double spend attempt! %s\n", txin.prevout.ToStringShort()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::ProcessTxLockRequest -- Double spend attempt! %s\n", txin.prevout.ToStringShort()); // do not fail here, let it go and see which one will get the votes to be locked // NOTIFY ZMQ CTransaction txCurrent = *txLockRequest.tx; // currently processed tx @@ -185,7 +185,7 @@ bool CInstantSend::CreateTxLockCandidate(const CTxLockRequest& txLockRequest) itLockCandidate->second.AddOutPointLock(txin.prevout); } } else { - LogPrint("instantsend", "CInstantSend::CreateTxLockCandidate -- seen, txid=%s\n", txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::CreateTxLockCandidate -- seen, txid=%s\n", txHash.ToString()); } return true; @@ -238,7 +238,7 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman) for (auto& outpointLockPair : txLockCandidate.mapOutPointLocks) { int nPrevoutHeight = GetUTXOHeight(outpointLockPair.first); if (nPrevoutHeight == -1) { - LogPrint("instantsend", "CInstantSend::Vote -- Failed to find UTXO %s\n", outpointLockPair.first.ToStringShort()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::Vote -- Failed to find UTXO %s\n", outpointLockPair.first.ToStringShort()); return; } @@ -247,17 +247,17 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman) int nRank; uint256 quorumModifierHash; if (!CMasternodeUtils::GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight)) { - LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternodeInfo.outpoint.ToStringShort()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternodeInfo.outpoint.ToStringShort()); continue; } int nSignaturesTotal = Params().GetConsensus().nInstantSendSigsTotal; if (nRank > nSignaturesTotal) { - LogPrint("instantsend", "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, nRank); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, nRank); continue; } - LogPrint("instantsend", "CInstantSend::Vote -- In the top %d (%d)\n", nSignaturesTotal, nRank); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::Vote -- In the top %d (%d)\n", nSignaturesTotal, nRank); std::map >::iterator itVoted = mapVotedOutpoints.find(outpointLockPair.first); @@ -326,7 +326,7 @@ bool CInstantSend::ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, C if (!vote.IsValid(pfrom, connman)) { // could be because of missing MN - LogPrint("instantsend", "CInstantSend::%s -- Vote is invalid, txid=%s\n", __func__, txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Vote is invalid, txid=%s\n", __func__, txHash.ToString()); return false; } @@ -350,7 +350,7 @@ bool CInstantSend::ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, C CreateEmptyTxLockCandidate(txHash); } bool fInserted = mapTxLockVotesOrphan.emplace(nVoteHash, vote).second; - LogPrint("instantsend", "CInstantSend::%s -- Orphan vote: txid=%s masternode=%s %s\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Orphan vote: txid=%s masternode=%s %s\n", __func__, txHash.ToString(), vote.GetMasternodeOutpoint().ToStringShort(), fInserted ? "new" : "seen"); // This tracks those messages and allows only the same rate as of the rest of the network @@ -362,7 +362,7 @@ bool CInstantSend::ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, C mapMasternodeOrphanVotes.emplace(vote.GetMasternodeOutpoint(), nMasternodeOrphanExpireTime); } else { if (itMnOV->second > GetTime() && itMnOV->second > GetAverageMasternodeOrphanVoteTime()) { - LogPrint("instantsend", "CInstantSend::%s -- masternode is spamming orphan Transaction Lock Votes: txid=%s masternode=%s\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- masternode is spamming orphan Transaction Lock Votes: txid=%s masternode=%s\n", __func__, txHash.ToString(), vote.GetMasternodeOutpoint().ToStringShort()); // Misbehaving(pfrom->id, 1); return false; @@ -378,11 +378,11 @@ bool CInstantSend::ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, C CTxLockCandidate& txLockCandidate = it->second; if (txLockCandidate.IsTimedOut()) { - LogPrint("instantsend", "CInstantSend::%s -- too late, Transaction Lock timed out, txid=%s\n", __func__, txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- too late, Transaction Lock timed out, txid=%s\n", __func__, txHash.ToString()); return false; } - LogPrint("instantsend", "CInstantSend::%s -- Transaction Lock Vote, txid=%s\n", __func__, txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Transaction Lock Vote, txid=%s\n", __func__, txHash.ToString()); UpdateVotedOutpoints(vote, txLockCandidate); @@ -393,7 +393,7 @@ bool CInstantSend::ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, C int nSignatures = txLockCandidate.CountVotes(); int nSignaturesMax = txLockCandidate.txLockRequest.GetMaxSignatures(); - LogPrint("instantsend", "CInstantSend::%s -- Transaction Lock signatures count: %d/%d, vote hash=%s\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Transaction Lock signatures count: %d/%d, vote hash=%s\n", __func__, nSignatures, nSignaturesMax, nVoteHash.ToString()); TryToFinalizeLockCandidate(txLockCandidate); @@ -421,11 +421,11 @@ bool CInstantSend::ProcessOrphanTxLockVote(const CTxLockVote& vote) CTxLockCandidate& txLockCandidate = it->second; if (txLockCandidate.IsTimedOut()) { - LogPrint("instantsend", "CInstantSend::%s -- too late, Transaction Lock timed out, txid=%s\n", __func__, txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- too late, Transaction Lock timed out, txid=%s\n", __func__, txHash.ToString()); return false; } - LogPrint("instantsend", "CInstantSend::%s -- Transaction Lock Vote, txid=%s\n", __func__, txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Transaction Lock Vote, txid=%s\n", __func__, txHash.ToString()); UpdateVotedOutpoints(vote, txLockCandidate); @@ -436,7 +436,7 @@ bool CInstantSend::ProcessOrphanTxLockVote(const CTxLockVote& vote) int nSignatures = txLockCandidate.CountVotes(); int nSignaturesMax = txLockCandidate.txLockRequest.GetMaxSignatures(); - LogPrint("instantsend", "CInstantSend::%s -- Transaction Lock signatures count: %d/%d, vote hash=%s\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Transaction Lock signatures count: %d/%d, vote hash=%s\n", __func__, nSignatures, nSignaturesMax, vote.GetHash().ToString()); return true; @@ -505,7 +505,7 @@ void CInstantSend::TryToFinalizeLockCandidate(const CTxLockCandidate& txLockCand uint256 txHash = txLockCandidate.txLockRequest.tx->GetHash(); if (txLockCandidate.IsAllOutPointsReady() && !IsLockedInstantSendTransaction(txHash)) { // we have enough votes now - LogPrint("instantsend", "CInstantSend::TryToFinalizeLockCandidate -- Transaction Lock is ready to complete, txid=%s\n", txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::TryToFinalizeLockCandidate -- Transaction Lock is ready to complete, txid=%s\n", txHash.ToString()); if (ResolveConflicts(txLockCandidate)) { LockTransactionInputs(txLockCandidate); UpdateLockedTransaction(txLockCandidate); @@ -541,7 +541,7 @@ void CInstantSend::UpdateLockedTransaction(const CTxLockCandidate& txLockCandida GetMainSignals().NotifyTransactionLock(*txLockCandidate.txLockRequest.tx); - LogPrint("instantsend", "CInstantSend::UpdateLockedTransaction -- done, txid=%s\n", txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::UpdateLockedTransaction -- done, txid=%s\n", txHash.ToString()); } void CInstantSend::LockTransactionInputs(const CTxLockCandidate& txLockCandidate) @@ -557,7 +557,7 @@ void CInstantSend::LockTransactionInputs(const CTxLockCandidate& txLockCandidate for (const auto& pair : txLockCandidate.mapOutPointLocks) { mapLockedOutpoints.insert(std::make_pair(pair.first, txHash)); } - LogPrint("instantsend", "CInstantSend::LockTransactionInputs -- done, txid=%s\n", txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::LockTransactionInputs -- done, txid=%s\n", txHash.ToString()); } bool CInstantSend::GetLockedOutPointTxHash(const COutPoint& outpoint, uint256& hashRet) @@ -628,7 +628,7 @@ bool CInstantSend::ResolveConflicts(const CTxLockCandidate& txLockCandidate) CTransactionRef txTmp; uint256 hashBlock; if (GetTransaction(txHash, txTmp, Params().GetConsensus(), hashBlock, true) && hashBlock != uint256()) { - LogPrint("instantsend", "CInstantSend::ResolveConflicts -- Done, %s is included in block %s\n", txHash.ToString(), hashBlock.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::ResolveConflicts -- Done, %s is included in block %s\n", txHash.ToString(), hashBlock.ToString()); return true; } // Not in block yet, make sure all its inputs are still unspent @@ -640,7 +640,7 @@ bool CInstantSend::ResolveConflicts(const CTxLockCandidate& txLockCandidate) return false; } } - LogPrint("instantsend", "CInstantSend::ResolveConflicts -- Done, txid=%s\n", txHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::ResolveConflicts -- Done, txid=%s\n", txHash.ToString()); return true; } @@ -690,7 +690,7 @@ void CInstantSend::CheckAndRemove() std::map::iterator itVote = mapTxLockVotes.begin(); while (itVote != mapTxLockVotes.end()) { if (itVote->second.IsExpired(nCachedBlockHeight)) { - LogPrint("instantsend", "CInstantSend::CheckAndRemove -- Removing expired vote: txid=%s masternode=%s\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::CheckAndRemove -- Removing expired vote: txid=%s masternode=%s\n", itVote->second.GetTxHash().ToString(), itVote->second.GetMasternodeOutpoint().ToStringShort()); mapTxLockVotes.erase(itVote++); } else { @@ -702,7 +702,7 @@ void CInstantSend::CheckAndRemove() std::map::iterator itOrphanVote = mapTxLockVotesOrphan.begin(); while (itOrphanVote != mapTxLockVotesOrphan.end()) { if (itOrphanVote->second.IsTimedOut()) { - LogPrint("instantsend", "CInstantSend::CheckAndRemove -- Removing timed out orphan vote: txid=%s masternode=%s\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::CheckAndRemove -- Removing timed out orphan vote: txid=%s masternode=%s\n", itOrphanVote->second.GetTxHash().ToString(), itOrphanVote->second.GetMasternodeOutpoint().ToStringShort()); mapTxLockVotes.erase(itOrphanVote->first); mapTxLockVotesOrphan.erase(itOrphanVote++); @@ -715,7 +715,7 @@ void CInstantSend::CheckAndRemove() itVote = mapTxLockVotes.begin(); while (itVote != mapTxLockVotes.end()) { if (itVote->second.IsFailed()) { - LogPrint("instantsend", "CInstantSend::CheckAndRemove -- Removing vote for failed lock attempt: txid=%s masternode=%s\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::CheckAndRemove -- Removing vote for failed lock attempt: txid=%s masternode=%s\n", itVote->second.GetTxHash().ToString(), itVote->second.GetMasternodeOutpoint().ToStringShort()); mapTxLockVotes.erase(itVote++); } else { @@ -727,7 +727,7 @@ void CInstantSend::CheckAndRemove() std::map::iterator itMasternodeOrphan = mapMasternodeOrphanVotes.begin(); while (itMasternodeOrphan != mapMasternodeOrphanVotes.end()) { if (itMasternodeOrphan->second < GetTime()) { - LogPrint("instantsend", "CInstantSend::CheckAndRemove -- Removing timed out orphan masternode vote: masternode=%s\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::CheckAndRemove -- Removing timed out orphan masternode vote: masternode=%s\n", itMasternodeOrphan->first.ToStringShort()); mapMasternodeOrphanVotes.erase(itMasternodeOrphan++); } else { @@ -895,12 +895,12 @@ void CInstantSend::SyncTransaction(const CTransaction& tx, const CBlockIndex *pi // When tx is 0-confirmed or conflicted, posInBlock is SYNC_TRANSACTION_NOT_IN_BLOCK and nHeightNew should be set to -1 int nHeightNew = posInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK ? -1 : pindex->nHeight; - LogPrint("instantsend", "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d\n", txHash.ToString(), nHeightNew); + LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d\n", txHash.ToString(), nHeightNew); // Check lock candidates std::map::iterator itLockCandidate = mapTxLockCandidates.find(txHash); if (itLockCandidate != mapTxLockCandidates.end()) { - LogPrint("instantsend", "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d lock candidate updated\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d lock candidate updated\n", txHash.ToString(), nHeightNew); itLockCandidate->second.SetConfirmedHeight(nHeightNew); // Loop through outpoint locks @@ -908,7 +908,7 @@ void CInstantSend::SyncTransaction(const CTransaction& tx, const CBlockIndex *pi // Check corresponding lock votes for (const auto& vote : pair.second.GetVotes()) { uint256 nVoteHash = vote.GetHash(); - LogPrint("instantsend", "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d vote %s updated\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d vote %s updated\n", txHash.ToString(), nHeightNew, nVoteHash.ToString()); const auto& it = mapTxLockVotes.find(nVoteHash); if (it != mapTxLockVotes.end()) { @@ -921,7 +921,7 @@ void CInstantSend::SyncTransaction(const CTransaction& tx, const CBlockIndex *pi // check orphan votes for (const auto& pair : mapTxLockVotesOrphan) { if (pair.second.GetTxHash() == txHash) { - LogPrint("instantsend", "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d vote %s updated\n", + LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d vote %s updated\n", txHash.ToString(), nHeightNew, pair.first.ToString()); mapTxLockVotes[pair.first].SetConfirmedHeight(nHeightNew); } @@ -961,12 +961,12 @@ bool CTxLockRequest::IsValid() const if (tx->vout.size() < 1) return false; if (tx->vin.size() > WARN_MANY_INPUTS) { - LogPrint("instantsend", "CTxLockRequest::IsValid -- WARNING: Too many inputs: tx=%s", ToString()); + LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- WARNING: Too many inputs: tx=%s", ToString()); } AssertLockHeld(cs_main); if (!CheckFinalTx(*tx)) { - LogPrint("instantsend", "CTxLockRequest::IsValid -- Transaction is not final: tx=%s", ToString()); + LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- Transaction is not final: tx=%s", ToString()); return false; } @@ -979,7 +979,7 @@ bool CTxLockRequest::IsValid() const Coin coin; if (!GetUTXOCoin(txin.prevout, coin)) { - LogPrint("instantsend", "CTxLockRequest::IsValid -- Failed to find UTXO %s\n", txin.prevout.ToStringShort()); + LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- Failed to find UTXO %s\n", txin.prevout.ToStringShort()); return false; } @@ -988,7 +988,7 @@ bool CTxLockRequest::IsValid() const int nConfirmationsRequired = nInstantSendConfirmationsRequired - 1; if (nTxAge < nConfirmationsRequired) { - LogPrint("instantsend", "CTxLockRequest::IsValid -- outpoint %s too new: nTxAge=%d, nConfirmationsRequired=%d, txid=%s\n", + LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- outpoint %s too new: nTxAge=%d, nConfirmationsRequired=%d, txid=%s\n", txin.prevout.ToStringShort(), nTxAge, nConfirmationsRequired, GetHash().ToString()); return false; } @@ -997,14 +997,14 @@ bool CTxLockRequest::IsValid() const } if (nValueIn > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) { - LogPrint("instantsend", "CTxLockRequest::IsValid -- Transaction value too high: nValueIn=%d, tx=%s", nValueIn, ToString()); + LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- Transaction value too high: nValueIn=%d, tx=%s", nValueIn, ToString()); return false; } CAmount nValueOut = tx->GetValueOut(); if (nValueIn - nValueOut < GetMinFee(false)) { - LogPrint("instantsend", "CTxLockRequest::IsValid -- did not include enough fees in transaction: fees=%d, tx=%s", nValueOut - nValueIn, ToString()); + LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- did not include enough fees in transaction: fees=%d, tx=%s", nValueOut - nValueIn, ToString()); return false; } @@ -1039,7 +1039,7 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const auto mnList = deterministicMNManager->GetListAtChainTip(); if (!mnList.HasValidMNByCollateral(outpointMasternode)) { - LogPrint("instantsend", "CTxLockVote::IsValid -- Unknown masternode %s\n", outpointMasternode.ToStringShort()); + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Unknown masternode %s\n", outpointMasternode.ToStringShort()); return false; } @@ -1049,17 +1049,17 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const if (!masternodeProTxHash.IsNull()) { auto dmn = mnList.GetValidMN(masternodeProTxHash); if (!dmn || dmn->collateralOutpoint != outpointMasternode) { - LogPrint("instantsend", "CTxLockVote::IsValid -- invalid masternodeProTxHash %s\n", masternodeProTxHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- invalid masternodeProTxHash %s\n", masternodeProTxHash.ToString()); return false; } } else { - LogPrint("instantsend", "CTxLockVote::IsValid -- missing masternodeProTxHash\n"); + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- missing masternodeProTxHash\n"); return false; } Coin coin; if (!GetUTXOCoin(outpoint, coin)) { - LogPrint("instantsend", "CTxLockVote::IsValid -- Failed to find UTXO %s\n", outpoint.ToStringShort()); + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Failed to find UTXO %s\n", outpoint.ToStringShort()); return false; } @@ -1069,24 +1069,24 @@ bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const uint256 expectedQuorumModifierHash; 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()); + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Can't calculate rank for masternode %s\n", outpointMasternode.ToStringShort()); return false; } if (!quorumModifierHash.IsNull()) { if (quorumModifierHash != expectedQuorumModifierHash) { - LogPrint("instantsend", "CTxLockVote::IsValid -- invalid quorumModifierHash %s, expected %s\n", quorumModifierHash.ToString(), expectedQuorumModifierHash.ToString()); + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- invalid quorumModifierHash %s, expected %s\n", quorumModifierHash.ToString(), expectedQuorumModifierHash.ToString()); return false; } } else { - LogPrint("instantsend", "CTxLockVote::IsValid -- missing quorumModifierHash\n"); + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- missing quorumModifierHash\n"); return false; } - LogPrint("instantsend", "CTxLockVote::IsValid -- Masternode %s, rank=%d\n", outpointMasternode.ToStringShort(), nRank); + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Masternode %s, rank=%d\n", outpointMasternode.ToStringShort(), nRank); int nSignaturesTotal = Params().GetConsensus().nInstantSendSigsTotal; if (nRank > nSignaturesTotal) { - LogPrint("instantsend", "CTxLockVote::IsValid -- Masternode %s is not in the top %d (%d), vote hash=%s\n", + LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Masternode %s is not in the top %d (%d), vote hash=%s\n", outpointMasternode.ToStringShort(), nSignaturesTotal, nRank, GetHash().ToString()); return false; } diff --git a/src/keepass.cpp b/src/keepass.cpp index b9e119d13748..97d96dfa0650 100644 --- a/src/keepass.cpp +++ b/src/keepass.cpp @@ -341,8 +341,8 @@ void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatusRet evhttp_add_header(output_headers, "Connection", "close"); // Logging of actual post data disabled as to not write passphrase in debug.log. Only enable temporarily when needed - //LogPrint("keepass", "CKeePassIntegrator::doHTTPPost -- send POST data: %s\n", strPost); - LogPrint("keepass", "CKeePassIntegrator::doHTTPPost -- send POST data\n"); + //LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- send POST data: %s\n", strPost); + LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- send POST data\n"); // boost::asio::streambuf request; // std::ostream request_stream(&request); @@ -351,7 +351,7 @@ void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatusRet // // Send the request. // boost::asio::write(socket, request); -// LogPrint("keepass", "CKeePassIntegrator::doHTTPPost -- request written\n"); +// LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- request written\n"); // // Read the response status line. The response streambuf will automatically // // grow to accommodate the entire line. The growth may be limited by passing @@ -359,7 +359,7 @@ void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatusRet // boost::asio::streambuf response; // boost::asio::read_until(socket, response, "\r\n"); -// LogPrint("keepass", "CKeePassIntegrator::doHTTPPost -- request status line read\n"); +// LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- request status line read\n"); // // Receive HTTP reply status // int nProto = 0; @@ -383,7 +383,7 @@ void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatusRet evhttp_connection_free(evcon); event_base_free(base); -// LogPrint("keepass", "CKeePassIntegrator::doHTTPPost -- reading response body start\n"); +// LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- reading response body start\n"); // // Read until EOF, writing data to output as we go. // while (boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error)) // { @@ -395,12 +395,12 @@ void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatusRet // } // } // } -// LogPrint("keepass", "CKeePassIntegrator::doHTTPPost -- reading response body end\n"); +// LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- reading response body end\n"); // // // Receive HTTP reply message headers and body // std::map mapHeaders; // ReadHTTPMessage(response_stream, mapHeaders, strResponse, nProto, std::numeric_limits::max()); -// LogPrint("keepass", "CKeePassIntegrator::doHTTPPost -- Processed body\n"); +// LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- Processed body\n"); nStatusRet = response.nStatus; if (response.nStatus == 0) @@ -431,7 +431,7 @@ void CKeePassIntegrator::rpcTestAssociation(bool bTriggerUnlock) doHTTPPost(request.getJson(), nStatus, strResponse); - LogPrint("keepass", "CKeePassIntegrator::rpcTestAssociation -- send result: status: %d response: %s\n", nStatus, strResponse); + LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcTestAssociation -- send result: status: %d response: %s\n", nStatus, strResponse); } std::vector CKeePassIntegrator::rpcGetLogins() @@ -452,8 +452,8 @@ std::vector CKeePassIntegrator::rpcGetLogins( doHTTPPost(request.getJson(), nStatus, strResponse); // Logging of actual response data disabled as to not write passphrase in debug.log. Only enable temporarily when needed - //LogPrint("keepass", "CKeePassIntegrator::rpcGetLogins -- send result: status: %d response: %s\n", nStatus, strResponse); - LogPrint("keepass", "CKeePassIntegrator::rpcGetLogins -- send result: status: %d\n", nStatus); + //LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcGetLogins -- send result: status: %d response: %s\n", nStatus, strResponse); + LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcGetLogins -- send result: status: %d\n", nStatus); if(nStatus != 200) { @@ -488,7 +488,7 @@ void CKeePassIntegrator::rpcSetLogin(const SecureString& sWalletPass, const Secu request.addStrParameter("Id", strKeePassId); request.addStrParameter("Url", sUrl); - LogPrint("keepass", "CKeePassIntegrator::rpcSetLogin -- send Url: %s\n", sUrl); + LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcSetLogin -- send Url: %s\n", sUrl); //request.addStrParameter("SubmitUrl", sSubmitUrl); // Is used to construct the entry title request.addStrParameter("Login", SecureString("dash")); @@ -504,7 +504,7 @@ void CKeePassIntegrator::rpcSetLogin(const SecureString& sWalletPass, const Secu doHTTPPost(request.getJson(), nStatus, strResponse); - LogPrint("keepass", "CKeePassIntegrator::rpcSetLogin -- send result: status: %d response: %s\n", nStatus, strResponse); + LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcSetLogin -- send result: status: %d response: %s\n", nStatus, strResponse); if(nStatus != 200) { @@ -547,7 +547,7 @@ void CKeePassIntegrator::rpcAssociate(std::string& strIdRet, SecureString& sKeyB doHTTPPost(request.getJson(), nStatus, strResponse); - LogPrint("keepass", "CKeePassIntegrator::rpcAssociate -- send result: status: %d response: %s\n", nStatus, strResponse); + LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcAssociate -- send result: status: %d response: %s\n", nStatus, strResponse); if(nStatus != 200) { diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index e34d81633494..fcea77968b2a 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -138,7 +138,7 @@ void CQuorum::StartCachePopulatorThread(std::shared_ptr _this) } cxxtimer::Timer t(true); - LogPrint("llmq", "CQuorum::StartCachePopulatorThread -- start\n"); + LogPrint(BCLog::LLMQ, "CQuorum::StartCachePopulatorThread -- start\n"); // this thread will exit after some time // when then later some other thread tries to get keys, it will be much faster @@ -149,7 +149,7 @@ void CQuorum::StartCachePopulatorThread(std::shared_ptr _this) _this->GetPubKeyShare(i); } } - LogPrint("llmq", "CQuorum::StartCachePopulatorThread -- done. time=%d\n", t.count()); + LogPrint(BCLog::LLMQ, "CQuorum::StartCachePopulatorThread -- done. time=%d\n", t.count()); }); } @@ -201,7 +201,7 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const } } if (!connections.empty()) { - if (LogAcceptCategory("llmq")) { + if (LogAcceptCategory(BCLog::LLMQ)) { auto mnList = deterministicMNManager->GetListAtChainTip(); std::string debugMsg = strprintf("CQuorumManager::%s -- adding masternodes quorum connections for quorum %s:\n", __func__, quorum->qc.quorumHash.ToString()); for (auto& c : connections) { @@ -212,7 +212,7 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToString(false)); } } - LogPrint("llmq", debugMsg.c_str()); + LogPrint(BCLog::LLMQ, debugMsg.c_str()); } g_connman->AddMasternodeQuorumNodes(llmqType, quorum->qc.quorumHash, connections); } @@ -221,7 +221,7 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const } for (auto& qh : connmanQuorumsToDelete) { - LogPrint("llmq", "CQuorumManager::%s -- removing masternodes quorum connections for quorum %s:\n", __func__, qh.ToString()); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- removing masternodes quorum connections for quorum %s:\n", __func__, qh.ToString()); g_connman->RemoveMasternodeQuorumNodes(llmqType, qh); } } @@ -243,7 +243,7 @@ bool CQuorumManager::BuildQuorumFromCommitment(const CFinalCommitment& qc, const quorum->WriteContributions(evoDb); hasValidVvec = true; } else { - LogPrint("llmq", "CQuorumManager::%s -- quorum.ReadContributions and BuildQuorumContributions for block %s failed\n", __func__, qc.quorumHash.ToString()); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- quorum.ReadContributions and BuildQuorumContributions for block %s failed\n", __func__, qc.quorumHash.ToString()); } } @@ -272,20 +272,20 @@ bool CQuorumManager::BuildQuorumContributions(const CFinalCommitment& fqc, std:: cxxtimer::Timer t2(true); quorumVvec = blsWorker.BuildQuorumVerificationVector(vvecs); if (quorumVvec == nullptr) { - LogPrint("llmq", "CQuorumManager::%s -- failed to build quorumVvec\n", __func__); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- failed to build quorumVvec\n", __func__); // without the quorum vvec, there can't be a skShare, so we fail here. Failure is not fatal here, as it still // allows to use the quorum as a non-member (verification through the quorum pub key) return false; } skShare = blsWorker.AggregateSecretKeys(skContributions); if (!skShare.IsValid()) { - LogPrint("llmq", "CQuorumManager::%s -- failed to build skShare\n", __func__); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- failed to build skShare\n", __func__); // We don't bail out here as this is not a fatal error and still allows us to recover public key shares (as we // have a valid quorum vvec at this point) } t2.stop(); - LogPrint("llmq", "CQuorumManager::%s -- built quorum vvec and skShare. time=%d\n", __func__, t2.count()); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- built quorum vvec and skShare. time=%d\n", __func__, t2.count()); quorum->quorumVvec = quorumVvec; quorum->skShare = skShare; @@ -364,7 +364,7 @@ CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, const uint25 auto quorumIt = mapBlockIndex.find(quorumHash); if (quorumIt == mapBlockIndex.end()) { - LogPrint("llmq", "CQuorumManager::%s -- block %s not found", __func__, quorumHash.ToString()); + LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- block %s not found", __func__, quorumHash.ToString()); return nullptr; } pindexQuorum = quorumIt->second; diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index eb0c3ba276d4..df72050d60a4 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -108,7 +108,7 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC return; } - LogPrint("llmq", "CQuorumBlockProcessor::%s -- received commitment for quorum %s:%d, validMembers=%d, signers=%d, peer=%d\n", __func__, + LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- received commitment for quorum %s:%d, validMembers=%d, signers=%d, peer=%d\n", __func__, qc.quorumHash.ToString(), qc.llmqType, qc.CountValidMembers(), qc.CountSigners(), pfrom->id); AddMinableCommitment(qc); @@ -219,7 +219,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH hasMinedCommitmentCache.erase(std::make_pair(params.type, quorumHash)); } - LogPrint("llmq", "CQuorumBlockProcessor::%s -- processed commitment from block. type=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s\n", __func__, + LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- processed commitment from block. type=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s\n", __func__, qc.llmqType, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), qc.quorumPublicKey.ToString()); return true; diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index ffa60866140a..92e958625ac5 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -159,7 +159,7 @@ void CChainLocksHandler::ProcessNewChainLock(NodeId from, const llmq::CChainLock EnforceBestChainLock(); }, 0); - LogPrint("chainlocks", "CChainLocksHandler::%s -- processed new CLSIG (%s), peer=%d\n", + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- processed new CLSIG (%s), peer=%d\n", __func__, clsig.ToString(), from); } @@ -280,7 +280,7 @@ void CChainLocksHandler::TrySignChainTip() } } - LogPrint("chainlocks", "CChainLocksHandler::%s -- trying to sign %s, height=%d\n", __func__, pindex->GetBlockHash().ToString(), pindex->nHeight); + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- trying to sign %s, height=%d\n", __func__, pindex->GetBlockHash().ToString(), pindex->nHeight); // When the new IX system is activated, we only try to ChainLock blocks which include safe transactions. A TX is // considered safe when it is ixlocked or at least known since 10 minutes (from mempool or block). These checks are @@ -292,12 +292,12 @@ void CChainLocksHandler::TrySignChainTip() if (pindex->nHeight - pindexWalk->nHeight > 5) { // no need to check further down, 6 confs is safe to assume that TXs below this height won't be // ixlocked anymore if they aren't already - LogPrint("chainlocks", "CChainLocksHandler::%s -- tip and previous 5 blocks all safe\n", __func__); + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- tip and previous 5 blocks all safe\n", __func__); break; } if (HasChainLock(pindexWalk->nHeight, pindexWalk->GetBlockHash())) { // we don't care about ixlocks for TXs that are ChainLocked already - LogPrint("chainlocks", "CChainLocksHandler::%s -- chainlock at height %d \n", __func__, pindexWalk->nHeight); + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- chainlock at height %d \n", __func__, pindexWalk->nHeight); break; } @@ -318,7 +318,7 @@ void CChainLocksHandler::TrySignChainTip() } if (txAge < WAIT_FOR_ISLOCK_TIMEOUT && !quorumInstantSendManager->IsLocked(txid)) { - LogPrint("chainlocks", "CChainLocksHandler::%s -- not signing block %s due to TX %s not being ixlocked and not old enough. age=%d\n", __func__, + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- not signing block %s due to TX %s not being ixlocked and not old enough. age=%d\n", __func__, pindexWalk->GetBlockHash().ToString(), txid.ToString(), txAge); return; } @@ -396,7 +396,7 @@ CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const if (!ret) { // This should only happen when freshly started. // If running for some time, SyncTransaction should have been called before which fills blockTxs. - LogPrint("chainlocks", "CChainLocksHandler::%s -- blockTxs for %s not found. Trying ReadBlockFromDisk\n", __func__, + LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- blockTxs for %s not found. Trying ReadBlockFromDisk\n", __func__, blockHash.ToString()); uint32_t blockTime; diff --git a/src/llmq/quorums_dkgsession.cpp b/src/llmq/quorums_dkgsession.cpp index 693a03f2e25b..c68db08bb154 100644 --- a/src/llmq/quorums_dkgsession.cpp +++ b/src/llmq/quorums_dkgsession.cpp @@ -65,7 +65,7 @@ CDKGLogger::CDKGLogger(const CDKGSession& _quorumDkg, const std::string& _func) } CDKGLogger::CDKGLogger(Consensus::LLMQType _llmqType, const uint256& _quorumHash, int _height, bool _areWeMember, const std::string& _func) : - CBatchedLogger("llmq-dkg", strprintf("QuorumDKG(type=%d, height=%d, member=%d, func=%s)", _llmqType, _height, _areWeMember, _func)) + CBatchedLogger(BCLog::LLMQ_DKG, strprintf("QuorumDKG(type=%d, height=%d, member=%d, func=%s)", _llmqType, _height, _areWeMember, _func)) { } diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index d76a6ecff652..b0de51044a92 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -45,7 +45,7 @@ void CDKGPendingMessages::PushPendingMessage(NodeId from, CDataStream& vRecv) LOCK2(cs_main, cs); if (!seenMessages.emplace(hash).second) { - LogPrint("llmq-dkg", "CDKGPendingMessages::%s -- already seen %s, peer=%d", __func__, from); + LogPrint(BCLog::LLMQ_DKG, "CDKGPendingMessages::%s -- already seen %s, peer=%d", __func__, from); return; } @@ -478,7 +478,7 @@ void CDKGSessionHandler::HandleDKGRound() } } if (!connections.empty()) { - if (LogAcceptCategory("llmq-dkg")) { + if (LogAcceptCategory(BCLog::LLMQ_DKG)) { std::string debugMsg = strprintf("CDKGSessionManager::%s -- adding masternodes quorum connections for quorum %s:\n", __func__, curSession->quorumHash.ToString()); auto mnList = deterministicMNManager->GetListAtChainTip(); for (const auto& c : connections) { @@ -489,7 +489,7 @@ void CDKGSessionHandler::HandleDKGRound() debugMsg += strprintf(" %s (%s)\n", c.ToString(), dmn->pdmnState->addr.ToString(false)); } } - LogPrint("llmq-dkg", debugMsg.c_str()); + LogPrint(BCLog::LLMQ_DKG, debugMsg.c_str()); } g_connman->AddMasternodeQuorumNodes(params.type, curQuorumHash, connections); } @@ -549,7 +549,7 @@ void CDKGSessionHandler::PhaseHandlerThread() status.aborted = true; return true; }); - LogPrint("llmq-dkg", "CDKGSessionHandler::%s -- aborted current DKG session for llmq=%s\n", __func__, params.name); + LogPrint(BCLog::LLMQ_DKG, "CDKGSessionHandler::%s -- aborted current DKG session for llmq=%s\n", __func__, params.name); } } } diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 807d9c7ed67b..f82fa1194b6f 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -491,7 +491,7 @@ bool CInstantSendManager::CheckCanLock(const CTransaction& tx, bool printDebug, // CAmount maxValueIn = sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE); // if (nValueIn > maxValueIn * COIN) { // if (printDebug) { -// LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: TX input value too high. nValueIn=%f, maxValueIn=%d", __func__, +// LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: TX input value too high. nValueIn=%f, maxValueIn=%d", __func__, // tx.GetHash().ToString(), nValueIn / (double)COIN, maxValueIn); // } // return false; @@ -512,7 +512,7 @@ bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebu auto mempoolTx = mempool.get(outpoint.hash); if (mempoolTx) { if (printDebug) { - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: parent mempool TX %s is not locked\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: parent mempool TX %s is not locked\n", __func__, txHash.ToString(), outpoint.hash.ToString()); } return false; @@ -523,7 +523,7 @@ bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebu // this relies on enabled txindex and won't work if we ever try to remove the requirement for txindex for masternodes if (!GetTransaction(outpoint.hash, tx, params, hashBlock, false)) { if (printDebug) { - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: failed to find parent TX %s\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: failed to find parent TX %s\n", __func__, txHash.ToString(), outpoint.hash.ToString()); } return false; @@ -540,7 +540,7 @@ bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebu if (nTxAge < nInstantSendConfirmationsRequired) { if (!llmq::chainLocksHandler->HasChainLock(pindexMined->nHeight, pindexMined->GetBlockHash())) { if (printDebug) { - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: outpoint %s too new and not ChainLocked. nTxAge=%d, nInstantSendConfirmationsRequired=%d\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: outpoint %s too new and not ChainLocked. nTxAge=%d, nInstantSendConfirmationsRequired=%d\n", __func__, txHash.ToString(), outpoint.ToStringShort(), nTxAge, nInstantSendConfirmationsRequired); } return false; @@ -594,11 +594,11 @@ void CInstantSendManager::HandleNewInputLockRecoveredSig(const CRecoveredSig& re return; } - if (LogAcceptCategory("instantsend")) { + if (LogAcceptCategory(BCLog::INSTANTSEND)) { for (auto& in : tx->vin) { auto id = ::SerializeHash(std::make_pair(INPUTLOCK_REQUESTID_PREFIX, in.prevout)); if (id == recoveredSig.id) { - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: got recovered sig for input %s\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: got recovered sig for input %s\n", __func__, txid.ToString(), in.prevout.ToStringShort()); break; } @@ -619,7 +619,7 @@ void CInstantSendManager::TrySignInstantSendLock(const CTransaction& tx) } } - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: got all recovered sigs, creating CInstantSendLock\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: got all recovered sigs, creating CInstantSendLock\n", __func__, tx.GetHash().ToString()); CInstantSendLock islock; @@ -706,7 +706,7 @@ void CInstantSendManager::ProcessMessageInstantSendLock(CNode* pfrom, const llmq return; } - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s, islock=%s: received islock, peer=%d\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: received islock, peer=%d\n", __func__, islock.txid.ToString(), hash.ToString(), pfrom->id); pendingInstantSendLocks.emplace(hash, std::make_pair(pfrom->id, std::move(islock))); @@ -836,7 +836,7 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks() auto& recSig = it->second.second; if (!quorumSigningManager->HasRecoveredSigForId(llmqType, recSig.id)) { recSig.UpdateHash(); - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s, islock=%s: passing reconstructed recSig to signing mgr, peer=%d\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: passing reconstructed recSig to signing mgr, peer=%d\n", __func__, islock.txid.ToString(), hash.ToString(), nodeId); quorumSigningManager->PushReconstructedRecoveredSig(recSig, quorum); } @@ -867,7 +867,7 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, const uint256& has // Let's see if the TX that was locked by this islock is already mined in a ChainLocked block. If yes, // we can simply ignore the islock, as the ChainLock implies locking of all TXs in that chain if (llmq::chainLocksHandler->HasChainLock(pindexMined->nHeight, pindexMined->GetBlockHash())) { - LogPrint("instantsend", "CInstantSendManager::%s -- txlock=%s, islock=%s: dropping islock as it already got a ChainLock in block %s, peer=%d\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txlock=%s, islock=%s: dropping islock as it already got a ChainLock in block %s, peer=%d\n", __func__, islock.txid.ToString(), hash.ToString(), hashBlock.ToString(), from); return; } @@ -877,7 +877,7 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, const uint256& has { LOCK(cs); - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s, islock=%s: processsing islock, peer=%d\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: processsing islock, peer=%d\n", __func__, islock.txid.ToString(), hash.ToString(), from); creatingInstantSendLocks.erase(islock.GetRequestId()); @@ -1115,7 +1115,7 @@ void CInstantSendManager::HandleFullyConfirmedBlock(const CBlockIndex* pindex) for (auto& p : removeISLocks) { auto& islockHash = p.first; auto& islock = p.second; - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s, islock=%s: removed islock as it got fully confirmed\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: removed islock as it got fully confirmed\n", __func__, islock->txid.ToString(), islockHash.ToString()); for (auto& in : islock->inputs) { @@ -1351,11 +1351,11 @@ bool CInstantSendManager::ProcessPendingRetryLockTxs() // CheckCanLock is already called by ProcessTx, so we should avoid calling it twice. But we also shouldn't spam // the logs when retrying TXs that are not ready yet. - if (LogAcceptCategory("instantsend")) { + if (LogAcceptCategory(BCLog::INSTANTSEND)) { if (!CheckCanLock(*tx, false, Params().GetConsensus())) { continue; } - LogPrint("instantsend", "CInstantSendManager::%s -- txid=%s: retrying to lock\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: retrying to lock\n", __func__, tx->GetHash().ToString()); } @@ -1365,7 +1365,7 @@ bool CInstantSendManager::ProcessPendingRetryLockTxs() if (retryCount != 0) { LOCK(cs); - LogPrint("instantsend", "CInstantSendManager::%s -- retried %d TXs. nonLockedTxs.size=%d\n", __func__, + LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- retried %d TXs. nonLockedTxs.size=%d\n", __func__, retryCount, nonLockedTxs.size()); } diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index ad9639a562a8..cd5f74f45aa5 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -325,7 +325,7 @@ void CRecoveredSigsDb::CleanupOldRecoveredSigs(int64_t maxAge) db.WriteBatch(batch); - LogPrint("llmq", "CRecoveredSigsDb::%d -- deleted %d entries\n", __func__, toDelete.size()); + LogPrint(BCLog::LLMQ, "CRecoveredSigsDb::%d -- deleted %d entries\n", __func__, toDelete.size()); } bool CRecoveredSigsDb::HasVotedOnId(Consensus::LLMQType llmqType, const uint256& id) @@ -390,7 +390,7 @@ void CRecoveredSigsDb::CleanupOldVotes(int64_t maxAge) db.WriteBatch(batch); - LogPrint("llmq", "CRecoveredSigsDb::%d -- deleted %d entries\n", __func__, cnt); + LogPrint(BCLog::LLMQ, "CRecoveredSigsDb::%d -- deleted %d entries\n", __func__, cnt); } ////////////////// @@ -444,7 +444,7 @@ void CSigningManager::ProcessMessageRecoveredSig(CNode* pfrom, const CRecoveredS return; } - LogPrint("llmq", "CSigningManager::%s -- signHash=%s, node=%d\n", __func__, CLLMQUtils::BuildSignHash(recoveredSig).ToString(), pfrom->id); + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- signHash=%s, node=%d\n", __func__, CLLMQUtils::BuildSignHash(recoveredSig).ToString(), pfrom->id); LOCK(cs); pendingRecoveredSigs[pfrom->id].emplace_back(recoveredSig); @@ -463,7 +463,7 @@ bool CSigningManager::PreVerifyRecoveredSig(NodeId nodeId, const CRecoveredSig& CQuorumCPtr quorum = quorumManager->GetQuorum(llmqType, recoveredSig.quorumHash); if (!quorum) { - LogPrint("llmq", "CSigningManager::%s -- quorum %s not found, node=%d\n", __func__, + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- quorum %s not found, node=%d\n", __func__, recoveredSig.quorumHash.ToString(), nodeId); return false; } @@ -520,13 +520,13 @@ void CSigningManager::CollectPendingRecoveredSigsToVerify( if (!retQuorums.count(quorumKey)) { CQuorumCPtr quorum = quorumManager->GetQuorum(llmqType, recSig.quorumHash); if (!quorum) { - LogPrint("llmq", "CSigningManager::%s -- quorum %s not found, node=%d\n", __func__, + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- quorum %s not found, node=%d\n", __func__, recSig.quorumHash.ToString(), nodeId); it = v.erase(it); continue; } if (!CLLMQUtils::IsQuorumActive(llmqType, quorum->qc.quorumHash)) { - LogPrint("llmq", "CSigningManager::%s -- quorum %s not active anymore, node=%d\n", __func__, + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- quorum %s not active anymore, node=%d\n", __func__, recSig.quorumHash.ToString(), nodeId); it = v.erase(it); continue; @@ -590,7 +590,7 @@ bool CSigningManager::ProcessPendingRecoveredSigs(CConnman& connman) batchVerifier.Verify(); verifyTimer.stop(); - LogPrint("llmq", "CSigningManager::%s -- verified recovered sig(s). count=%d, vt=%d, nodes=%d\n", __func__, verifyCount, verifyTimer.count(), recSigsByNode.size()); + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- verified recovered sig(s). count=%d, vt=%d, nodes=%d\n", __func__, verifyCount, verifyTimer.count(), recSigsByNode.size()); std::unordered_set processed; for (auto& p : recSigsByNode) { @@ -634,7 +634,7 @@ void CSigningManager::ProcessRecoveredSig(NodeId nodeId, const CRecoveredSig& re auto signHash = CLLMQUtils::BuildSignHash(recoveredSig); - LogPrint("llmq", "CSigningManager::%s -- valid recSig. signHash=%s, id=%s, msgHash=%s, node=%d\n", __func__, + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- valid recSig. signHash=%s, id=%s, msgHash=%s, node=%d\n", __func__, signHash.ToString(), recoveredSig.id.ToString(), recoveredSig.msgHash.ToString(), nodeId); if (db.HasRecoveredSigForId(llmqType, recoveredSig.id)) { @@ -726,7 +726,7 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, const uint LogPrintf("CSigningManager::%s -- already voted for id=%s and msgHash=%s. Not voting on conflicting msgHash=%s\n", __func__, id.ToString(), prevMsgHash.ToString(), msgHash.ToString()); } else { - LogPrint("llmq", "CSigningManager::%s -- already voted for id=%s and msgHash=%s. Not voting again.\n", __func__, + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- already voted for id=%s and msgHash=%s. Not voting again.\n", __func__, id.ToString(), prevMsgHash.ToString()); } return false; @@ -752,12 +752,12 @@ bool CSigningManager::AsyncSignIfMember(Consensus::LLMQType llmqType, const uint // TODO fix this by re-signing when the next block arrives, but only when that block results in a change of the quorum list and no recovered signature has been created in the mean time CQuorumCPtr quorum = SelectQuorumForSigning(llmqType, tipHeight, id); if (!quorum) { - LogPrint("llmq", "CSigningManager::%s -- failed to select quorum. id=%s, msgHash=%s\n", __func__, id.ToString(), msgHash.ToString()); + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- failed to select quorum. id=%s, msgHash=%s\n", __func__, id.ToString(), msgHash.ToString()); return false; } if (!quorum->IsValidMember(activeMasternodeInfo.proTxHash)) { - //LogPrint("llmq", "CSigningManager::%s -- we're not a valid member of quorum %s\n", __func__, quorum->quorumHash.ToString()); + //LogPrint(BCLog::LLMQ, "CSigningManager::%s -- we're not a valid member of quorum %s\n", __func__, quorum->quorumHash.ToString()); return false; } diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index 89ea8689770a..42d4f3f55a50 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -303,12 +303,12 @@ bool CSigSharesManager::ProcessMessageSigSesAnn(CNode* pfrom, const CSigSesAnn& return false; } - LogPrint("llmq-sigs", "CSigSharesManager::%s -- ann={%s}, node=%d\n", __func__, ann.ToString(), pfrom->id); + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- ann={%s}, node=%d\n", __func__, ann.ToString(), pfrom->id); auto quorum = quorumManager->GetQuorum(llmqType, ann.quorumHash); if (!quorum) { // TODO should we ban here? - LogPrint("llmq-sigs", "CSigSharesManager::%s -- quorum %s not found, node=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- quorum %s not found, node=%d\n", __func__, ann.quorumHash.ToString(), pfrom->id); return true; // let's still try other announcements from the same message } @@ -353,12 +353,12 @@ bool CSigSharesManager::ProcessMessageSigSharesInv(CNode* pfrom, const CSigShare return true; } - LogPrint("llmq-sigs", "CSigSharesManager::%s -- signHash=%s, inv={%s}, node=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signHash=%s, inv={%s}, node=%d\n", __func__, sessionInfo.signHash.ToString(), inv.ToString(), pfrom->id); if (sessionInfo.quorum->quorumVvec == nullptr) { // TODO we should allow to ask other nodes for the quorum vvec if we missed it in the DKG - LogPrint("llmq-sigs", "CSigSharesManager::%s -- we don't have the quorum vvec for %s, not requesting sig shares. node=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- we don't have the quorum vvec for %s, not requesting sig shares. node=%d\n", __func__, sessionInfo.quorumHash.ToString(), pfrom->id); return true; } @@ -390,7 +390,7 @@ bool CSigSharesManager::ProcessMessageGetSigShares(CNode* pfrom, const CSigShare return true; } - LogPrint("llmq-sigs", "CSigSharesManager::%s -- signHash=%s, inv={%s}, node=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signHash=%s, inv={%s}, node=%d\n", __func__, sessionInfo.signHash.ToString(), inv.ToString(), pfrom->id); LOCK(cs); @@ -444,7 +444,7 @@ bool CSigSharesManager::ProcessMessageBatchedSigShares(CNode* pfrom, const CBatc } } - LogPrint("llmq-sigs", "CSigSharesManager::%s -- signHash=%s, shares=%d, new=%d, inv={%s}, node=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signHash=%s, shares=%d, new=%d, inv={%s}, node=%d\n", __func__, sessionInfo.signHash.ToString(), batchedSigShares.sigShares.size(), sigShares.size(), batchedSigShares.ToInvString(), pfrom->id); if (sigShares.empty()) { @@ -473,7 +473,7 @@ bool CSigSharesManager::PreVerifyBatchedSigShares(NodeId nodeId, const CSigShare } if (session.quorum->quorumVvec == nullptr) { // TODO we should allow to ask other nodes for the quorum vvec if we missed it in the DKG - LogPrint("llmq-sigs", "CSigSharesManager::%s -- we don't have the quorum vvec for %s, no verification possible. node=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- we don't have the quorum vvec for %s, no verification possible. node=%d\n", __func__, session.quorumHash.ToString(), nodeId); return false; } @@ -614,7 +614,7 @@ bool CSigSharesManager::ProcessPendingSigShares(CConnman& connman) batchVerifier.Verify(); verifyTimer.stop(); - LogPrint("llmq-sigs", "CSigSharesManager::%s -- verified sig shares. count=%d, vt=%d, nodes=%d\n", __func__, verifyCount, verifyTimer.count(), sigSharesByNodes.size()); + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- verified sig shares. count=%d, vt=%d, nodes=%d\n", __func__, verifyCount, verifyTimer.count(), sigSharesByNodes.size()); for (auto& p : sigSharesByNodes) { auto nodeId = p.first; @@ -649,7 +649,7 @@ void CSigSharesManager::ProcessPendingSigSharesFromNode(NodeId nodeId, } t.stop(); - LogPrint("llmq-sigs", "CSigSharesManager::%s -- processed sigShare batch. shares=%d, time=%d, node=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- processed sigShare batch. shares=%d, time=%d, node=%d\n", __func__, sigShares.size(), t.count(), nodeId); } @@ -754,7 +754,7 @@ void CSigSharesManager::TryRecoverSig(const CQuorumCPtr& quorum, const uint256& return; } - LogPrint("llmq-sigs", "CSigSharesManager::%s -- recovered signature. id=%s, msgHash=%s, time=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- recovered signature. id=%s, msgHash=%s, time=%d\n", __func__, id.ToString(), msgHash.ToString(), t.count()); CRecoveredSig rs; @@ -810,7 +810,7 @@ void CSigSharesManager::CollectSigSharesToRequest(std::unordered_map= SIG_SHARE_REQUEST_TIMEOUT) { // timeout while waiting for this one, so retry it with another node - LogPrint("llmq-sigs", "CSigSharesManager::CollectSigSharesToRequest -- timeout while waiting for %s-%d, node=%d\n", + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::CollectSigSharesToRequest -- timeout while waiting for %s-%d, node=%d\n", k.first.ToString(), k.second, nodeId); return true; } @@ -845,7 +845,7 @@ void CSigSharesManager::CollectSigSharesToRequest(std::unordered_mapsecond >= SIG_SHARE_REQUEST_TIMEOUT && nodeId != p->first) { // other node timed out, re-request from this node - LogPrint("llmq-sigs", "CSigSharesManager::%s -- other node timeout while waiting for %s-%d, re-request from=%d, node=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- other node timeout while waiting for %s-%d, re-request from=%d, node=%d\n", __func__, k.first.ToString(), k.second, nodeId, p->first); } else { continue; @@ -1043,7 +1043,7 @@ bool CSigSharesManager::SendMessages() std::vector msgs; msgs.reserve(it1->second.size()); for (auto& sigSesAnn : it1->second) { - LogPrint("llmq-sigs", "CSigSharesManager::SendMessages -- QSIGSESANN signHash=%s, sessionId=%d, node=%d\n", + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::SendMessages -- QSIGSESANN signHash=%s, sessionId=%d, node=%d\n", CLLMQUtils::BuildSignHash(sigSesAnn).ToString(), sigSesAnn.sessionId, pnode->id); msgs.emplace_back(sigSesAnn); if (msgs.size() == MAX_MSGS_CNT_QSIGSESANN) { @@ -1063,7 +1063,7 @@ bool CSigSharesManager::SendMessages() std::vector msgs; for (auto& p : it->second) { assert(p.second.CountSet() != 0); - LogPrint("llmq-sigs", "CSigSharesManager::SendMessages -- QGETSIGSHARES signHash=%s, inv={%s}, node=%d\n", + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::SendMessages -- QGETSIGSHARES signHash=%s, inv={%s}, node=%d\n", p.first.ToString(), p.second.ToString(), pnode->id); msgs.emplace_back(std::move(p.second)); if (msgs.size() == MAX_MSGS_CNT_QGETSIGSHARES) { @@ -1084,7 +1084,7 @@ bool CSigSharesManager::SendMessages() std::vector msgs; for (auto& p : jt->second) { assert(!p.second.sigShares.empty()); - LogPrint("llmq-sigs", "CSigSharesManager::SendMessages -- QBSIGSHARES signHash=%s, inv={%s}, node=%d\n", + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::SendMessages -- QBSIGSHARES signHash=%s, inv={%s}, node=%d\n", p.first.ToString(), p.second.ToInvString(), pnode->id); if (totalSigsCount + p.second.sigShares.size() > MAX_MSGS_TOTAL_BATCHED_SIGS) { g_connman->PushMessage(pnode, msgMaker.Make(NetMsgType::QBSIGSHARES, msgs), false); @@ -1107,7 +1107,7 @@ bool CSigSharesManager::SendMessages() std::vector msgs; for (auto& p : kt->second) { assert(p.second.CountSet() != 0); - LogPrint("llmq-sigs", "CSigSharesManager::SendMessages -- QSIGSHARESINV signHash=%s, inv={%s}, node=%d\n", + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::SendMessages -- QSIGSHARESINV signHash=%s, inv={%s}, node=%d\n", p.first.ToString(), p.second.ToString(), pnode->id); msgs.emplace_back(std::move(p.second)); if (msgs.size() == MAX_MSGS_CNT_QSIGSHARESINV) { @@ -1232,7 +1232,7 @@ void CSigSharesManager::Cleanup() auto& oneSigShare = m->begin()->second; std::string strMissingMembers; - if (LogAcceptCategory("llmq")) { + if (LogAcceptCategory(BCLog::LLMQ_SIGS)) { auto quorumIt = quorums.find(std::make_pair((Consensus::LLMQType)oneSigShare.llmqType, oneSigShare.quorumHash)); if (quorumIt != quorums.end()) { auto& quorum = quorumIt->second; @@ -1245,10 +1245,10 @@ void CSigSharesManager::Cleanup() } } - LogPrint("llmq-sigs", "CSigSharesManager::%s -- signing session timed out. signHash=%s, id=%s, msgHash=%s, sigShareCount=%d, missingMembers=%s\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signing session timed out. signHash=%s, id=%s, msgHash=%s, sigShareCount=%d, missingMembers=%s\n", __func__, signHash.ToString(), oneSigShare.id.ToString(), oneSigShare.msgHash.ToString(), count, strMissingMembers); } else { - LogPrint("llmq-sigs", "CSigSharesManager::%s -- signing session timed out. signHash=%s, sigShareCount=%d\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signing session timed out. signHash=%s, sigShareCount=%d\n", __func__, signHash.ToString(), count); } RemoveSigSharesForSession(signHash); @@ -1404,7 +1404,7 @@ void CSigSharesManager::Sign(const CQuorumCPtr& quorum, const uint256& id, const CBLSSecretKey skShare = quorum->GetSkShare(); if (!skShare.IsValid()) { - LogPrint("llmq-sigs", "CSigSharesManager::%s -- we don't have our skShare for quorum %s\n", __func__, quorum->qc.quorumHash.ToString()); + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- we don't have our skShare for quorum %s\n", __func__, quorum->qc.quorumHash.ToString()); return; } @@ -1431,7 +1431,7 @@ void CSigSharesManager::Sign(const CQuorumCPtr& quorum, const uint256& id, const sigShare.UpdateKey(); - LogPrint("llmq-sigs", "CSigSharesManager::%s -- signed sigShare. signHash=%s, id=%s, msgHash=%s, llmqType=%d, quorum=%s, time=%s\n", __func__, + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signed sigShare. signHash=%s, id=%s, msgHash=%s, llmqType=%d, quorum=%s, time=%s\n", __func__, signHash.ToString(), sigShare.id.ToString(), sigShare.msgHash.ToString(), quorum->params.type, quorum->qc.quorumHash.ToString(), t.count()); ProcessSigShare(-1, sigShare, *g_connman, quorum); } diff --git a/src/masternode/masternode-payments.cpp b/src/masternode/masternode-payments.cpp index d6e2af5f6aee..6a23b22d85f9 100644 --- a/src/masternode/masternode-payments.cpp +++ b/src/masternode/masternode-payments.cpp @@ -45,7 +45,7 @@ bool IsOldBudgetBlockValueValid(const CBlock& block, int nBlockHeight, CAmount b if(masternodeSync.IsSynced()) { // no old budget blocks should be accepted here on mainnet, // testnet/devnet/regtest should produce regular blocks only - LogPrint("gobject", "%s -- WARNING: Client synced but old budget system is disabled, checking block value against block reward\n", __func__); + LogPrint(BCLog::GOBJECT, "%s -- WARNING: Client synced but old budget system is disabled, checking block value against block reward\n", __func__); if(!isBlockRewardValueMet) { strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, old budgets are disabled", nBlockHeight, block.vtx[0]->GetValueOut(), blockReward); @@ -53,10 +53,10 @@ bool IsOldBudgetBlockValueValid(const CBlock& block, int nBlockHeight, CAmount b return isBlockRewardValueMet; } // when not synced, rely on online nodes (all networks) - LogPrint("gobject", "%s -- WARNING: Skipping old budget block value checks, accepting block\n", __func__); + LogPrint(BCLog::GOBJECT, "%s -- WARNING: Skipping old budget block value checks, accepting block\n", __func__); return true; } - // LogPrint("gobject", "%s -- Block is not in budget cycle window, checking block value against block reward\n", __func__); + // LogPrint(BCLog::GOBJECT, "%s -- Block is not in budget cycle window, checking block value against block reward\n", __func__); if(!isBlockRewardValueMet) { strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, block is not in old budget cycle window", nBlockHeight, block.vtx[0]->GetValueOut(), blockReward); @@ -94,12 +94,12 @@ bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockRewar return IsOldBudgetBlockValueValid(block, nBlockHeight, blockReward, strErrorRet); } - if(fDebug) LogPrintf("block.vtx[0]->GetValueOut() %lld <= blockReward %lld\n", block.vtx[0]->GetValueOut(), blockReward); + LogPrint(BCLog::MNPAYMENTS, "block.vtx[0]->GetValueOut() %lld <= blockReward %lld\n", block.vtx[0]->GetValueOut(), blockReward); CAmount nSuperblockMaxValue = blockReward + CSuperblock::GetPaymentsLimit(nBlockHeight); bool isSuperblockMaxValueMet = (block.vtx[0]->GetValueOut() <= nSuperblockMaxValue); - LogPrint("gobject", "block.vtx[0]->GetValueOut() %lld <= nSuperblockMaxValue %lld\n", block.vtx[0]->GetValueOut(), nSuperblockMaxValue); + LogPrint(BCLog::GOBJECT, "block.vtx[0]->GetValueOut() %lld <= nSuperblockMaxValue %lld\n", block.vtx[0]->GetValueOut(), nSuperblockMaxValue); if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) { // can't possibly be a superblock, so lets just check for block reward limits @@ -118,7 +118,7 @@ bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockRewar } if(!masternodeSync.IsSynced() || fLiteMode) { - if(fDebug) LogPrintf("%s -- WARNING: Not enough data, checked superblock max bounds only\n", __func__); + LogPrint(BCLog::MNPAYMENTS, "%s -- WARNING: Not enough data, checked superblock max bounds only\n", __func__); // not enough data for full checks but at least we know that the superblock limits were honored. // We rely on the network to have followed the correct chain in this case return true; @@ -129,7 +129,7 @@ bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockRewar if (!sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) { // should NOT allow superblocks at all, when superblocks are disabled // revert to block reward limits in this case - LogPrint("gobject", "%s -- Superblocks are disabled, no superblocks allowed\n", __func__); + LogPrint(BCLog::GOBJECT, "%s -- Superblocks are disabled, no superblocks allowed\n", __func__); if(!isBlockRewardValueMet) { strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, superblocks are disabled", nBlockHeight, block.vtx[0]->GetValueOut(), blockReward); @@ -164,7 +164,7 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc { 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__); + LogPrint(BCLog::MNPAYMENTS, "%s -- WARNING: Not enough data, skipping block payee checks\n", __func__); return true; } @@ -177,7 +177,7 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc // NOTE: old budget system is disabled since 12.1 and we should never enter this branch // anymore when sync is finished (on mainnet). We have no old budget data but these blocks // have tons of confirmations and can be safely accepted without payee verification - LogPrint("gobject", "%s -- WARNING: Client synced but old budget system is disabled, accepting any payee\n", __func__); + LogPrint(BCLog::GOBJECT, "%s -- WARNING: Client synced but old budget system is disabled, accepting any payee\n", __func__); return true; } @@ -187,7 +187,7 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) { if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) { if(CSuperblockManager::IsValid(txNew, nBlockHeight, blockReward)) { - LogPrint("gobject", "%s -- Valid superblock at height %d: %s", __func__, nBlockHeight, txNew.ToString()); + LogPrint(BCLog::GOBJECT, "%s -- Valid superblock at height %d: %s", __func__, nBlockHeight, txNew.ToString()); // continue validation, should also pay MN } else { LogPrintf("%s -- ERROR: Invalid superblock detected at height %d: %s", __func__, nBlockHeight, txNew.ToString()); @@ -195,16 +195,16 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc return false; } } else { - LogPrint("gobject", "%s -- No triggered superblock detected at height %d\n", __func__, nBlockHeight); + LogPrint(BCLog::GOBJECT, "%s -- No triggered superblock detected at height %d\n", __func__, nBlockHeight); } } else { // should NOT allow superblocks at all, when superblocks are disabled - LogPrint("gobject", "%s -- Superblocks are disabled, no superblocks allowed\n", __func__); + LogPrint(BCLog::GOBJECT, "%s -- Superblocks are disabled, no superblocks allowed\n", __func__); } // 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()); + LogPrint(BCLog::MNPAYMENTS, "%s -- Valid masternode payment at height %d: %s", __func__, nBlockHeight, txNew.ToString()); return true; } @@ -218,12 +218,12 @@ void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blo // (height should be validated inside) if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED) && CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) { - LogPrint("gobject", "%s -- triggered superblock creation at height %d\n", __func__, nBlockHeight); + LogPrint(BCLog::GOBJECT, "%s -- triggered superblock creation at height %d\n", __func__, nBlockHeight); CSuperblockManager::GetSuperblockPayments(nBlockHeight, voutSuperblockPaymentsRet); } if (!mnpayments.GetMasternodeTxOuts(nBlockHeight, blockReward, voutMasternodePaymentsRet)) { - LogPrint("mnpayments", "%s -- no masternode to pay (MN list probably empty)\n", __func__); + LogPrint(BCLog::MNPAYMENTS, "%s -- no masternode to pay (MN list probably empty)\n", __func__); } txNew.vout.insert(txNew.vout.end(), voutMasternodePaymentsRet.begin(), voutMasternodePaymentsRet.end()); @@ -238,7 +238,7 @@ void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blo voutMasternodeStr += txout.ToString(); } - LogPrint("mnpayments", "%s -- nBlockHeight %d blockReward %lld voutMasternodePaymentsRet \"%s\" txNew %s", __func__, + LogPrint(BCLog::MNPAYMENTS, "%s -- nBlockHeight %d blockReward %lld voutMasternodePaymentsRet \"%s\" txNew %s", __func__, nBlockHeight, blockReward, voutMasternodeStr, txNew.ToString()); } diff --git a/src/masternode/masternode-sync.cpp b/src/masternode/masternode-sync.cpp index 1dea1bba8bf3..47bf99017696 100644 --- a/src/masternode/masternode-sync.cpp +++ b/src/masternode/masternode-sync.cpp @@ -35,7 +35,7 @@ void CMasternodeSync::BumpAssetLastTime(const std::string& strFuncName) { if(IsSynced() || IsFailed()) return; nTimeLastBumped = GetTime(); - LogPrint("mnsync", "CMasternodeSync::BumpAssetLastTime -- %s\n", strFuncName); + LogPrint(BCLog::MNSYNC, "CMasternodeSync::BumpAssetLastTime -- %s\n", strFuncName); } std::string CMasternodeSync::GetAssetName() @@ -221,7 +221,7 @@ void CMasternodeSync::ProcessTick(CConnman& connman) // GOVOBJ : SYNC GOVERNANCE ITEMS FROM OUR PEERS if(nCurrentAsset == MASTERNODE_SYNC_GOVERNANCE) { - LogPrint("gobject", "CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d nTimeLastBumped %lld GetTime() %lld diff %lld\n", nTick, nCurrentAsset, nTimeLastBumped, GetTime(), GetTime() - nTimeLastBumped); + LogPrint(BCLog::GOBJECT, "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) { @@ -301,7 +301,7 @@ void CMasternodeSync::SendGovernanceSyncRequest(CNode* pnode, CConnman& connman) void CMasternodeSync::AcceptedBlockHeader(const CBlockIndex *pindexNew) { - LogPrint("mnsync", "CMasternodeSync::AcceptedBlockHeader -- pindexNew->nHeight: %d\n", pindexNew->nHeight); + LogPrint(BCLog::MNSYNC, "CMasternodeSync::AcceptedBlockHeader -- pindexNew->nHeight: %d\n", pindexNew->nHeight); if (!IsBlockchainSynced()) { // Postpone timeout each time new block header arrives while we are still syncing blockchain @@ -311,7 +311,7 @@ void CMasternodeSync::AcceptedBlockHeader(const CBlockIndex *pindexNew) void CMasternodeSync::NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload, CConnman& connman) { - LogPrint("mnsync", "CMasternodeSync::NotifyHeaderTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload); + LogPrint(BCLog::MNSYNC, "CMasternodeSync::NotifyHeaderTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload); if (IsFailed() || IsSynced() || !pindexBestHeader) return; @@ -324,7 +324,7 @@ void CMasternodeSync::NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitia void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitialDownload, CConnman& connman) { - LogPrint("mnsync", "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload); + LogPrint(BCLog::MNSYNC, "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d fInitialDownload=%d\n", pindexNew->nHeight, fInitialDownload); if (IsFailed() || IsSynced() || !pindexBestHeader) return; @@ -359,7 +359,7 @@ void CMasternodeSync::UpdatedBlockTip(const CBlockIndex *pindexNew, bool fInitia fReachedBestHeader = fReachedBestHeaderNew; - LogPrint("mnsync", "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d pindexBestHeader->nHeight: %d fInitialDownload=%d fReachedBestHeader=%d\n", + LogPrint(BCLog::MNSYNC, "CMasternodeSync::UpdatedBlockTip -- pindexNew->nHeight: %d pindexBestHeader->nHeight: %d fInitialDownload=%d fReachedBestHeader=%d\n", pindexNew->nHeight, pindexBestHeader->nHeight, fInitialDownload, fReachedBestHeader); if (!IsBlockchainSynced() && fReachedBestHeader) { diff --git a/src/miner.cpp b/src/miner.cpp index 68a32ad9e004..93591da4e2bb 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -242,7 +242,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc } int64_t nTime2 = GetTimeMicros(); - LogPrint("bench", "CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms)\n", 0.001 * (nTime1 - nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart)); + LogPrint(BCLog::BENCHMARK, "CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms)\n", 0.001 * (nTime1 - nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart)); return std::move(pblocktemplate); } diff --git a/src/net.cpp b/src/net.cpp index cefb8b5af7fc..ce125ac95045 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -201,7 +201,7 @@ void AdvertiseLocal(CNode *pnode) } if (addrLocal.IsRoutable()) { - LogPrint("net", "AdvertiseLocal: advertising address %s\n", addrLocal.ToString()); + LogPrint(BCLog::NET, "AdvertiseLocal: advertising address %s\n", addrLocal.ToString()); FastRandomContext insecure_rand; pnode->PushAddress(addrLocal, insecure_rand); } @@ -369,7 +369,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo } /// debug print - LogPrint("net", "trying connection %s lastseen=%.1fhrs\n", + LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n", pszDest ? pszDest : addrConnect.ToString(), pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0); @@ -438,7 +438,7 @@ void CConnman::DumpBanlist() if (!bandb.Write(banmap)) SetBannedSetDirty(true); - LogPrint("net", "Flushed %d banned node ips/subnets to banlist.dat %dms\n", + LogPrint(BCLog::NET, "Flushed %d banned node ips/subnets to banlist.dat %dms\n", banmap.size(), GetTimeMillis() - nStart); } @@ -448,7 +448,7 @@ void CNode::CloseSocketDisconnect() LOCK(cs_hSocket); if (hSocket != INVALID_SOCKET) { - LogPrint("net", "disconnecting peer=%d\n", id); + LogPrint(BCLog::NET, "disconnecting peer=%d\n", id); CloseSocket(hSocket); } } @@ -576,7 +576,7 @@ void CConnman::SweepBanned() { setBanned.erase(it++); setBannedIsDirty = true; - LogPrint("net", "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, subNet.ToString()); + LogPrint(BCLog::NET, "%s: Removed banned node ip/subnet from banlist.dat: %s\n", __func__, subNet.ToString()); } else ++it; @@ -728,7 +728,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete // expected to be very small. This protects against attackers filling up memory by sending oversized // VERSION messages while the incoming connection is still protected against eviction if (msg.hdr.nMessageSize > 1024) { - LogPrint("net", "Oversized VERSION/VERACK message from peer=%i, disconnecting\n", GetId()); + LogPrint(BCLog::NET, "Oversized VERSION/VERACK message from peer=%i, disconnecting\n", GetId()); return false; } } @@ -741,7 +741,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete return false; if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) { - LogPrint("net", "Oversized message from peer=%i, disconnecting\n", GetId()); + LogPrint(BCLog::NET, "Oversized message from peer=%i, disconnecting\n", GetId()); return false; } @@ -1148,7 +1148,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { { if (!AttemptToEvictConnection()) { // No connection to evict, disconnect the new connection - LogPrint("net", "failed to find an eviction candidate - connection dropped (full)\n"); + LogPrint(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n"); CloseSocket(hSocket); return; } @@ -1157,7 +1157,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { // don't accept incoming connections until fully synced if(fMasternodeMode && !masternodeSync.IsSynced()) { - LogPrint("net", "AcceptConnection -- masternode is not synced yet, skipping inbound connection attempt\n"); + LogPrint(BCLog::NET, "AcceptConnection -- masternode is not synced yet, skipping inbound connection attempt\n"); CloseSocket(hSocket); return; } @@ -1170,7 +1170,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { pnode->fWhitelisted = whitelisted; GetNodeSignals().InitializeNode(pnode, *this); - LogPrint("net", "connection from %s accepted\n", addr.ToString()); + LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString()); { LOCK(cs_vNodes); @@ -1347,7 +1347,7 @@ void CConnman::ThreadSocketHandler() #ifndef WIN32 // drain the wakeup pipe if (FD_ISSET(wakeupPipe[0], &fdsetRecv)) { - LogPrint("net", "woke up select()\n"); + LogPrint(BCLog::NET, "woke up select()\n"); char buf[128]; while (true) { int r = read(wakeupPipe[0], buf, sizeof(buf)); @@ -1431,8 +1431,9 @@ void CConnman::ThreadSocketHandler() else if (nBytes == 0) { // socket closed gracefully - if (!pnode->fDisconnect) - LogPrint("net", "socket closed\n"); + if (!pnode->fDisconnect) { + LogPrint(BCLog::NET, "socket closed\n"); + } pnode->CloseSocketDisconnect(); } else if (nBytes < 0) @@ -1470,7 +1471,7 @@ void CConnman::ThreadSocketHandler() { if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) { - LogPrint("net", "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id); + LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id); pnode->fDisconnect = true; } else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL) @@ -1515,11 +1516,11 @@ void CConnman::WakeSelect() return; } - LogPrint("net", "waking up select()\n"); + LogPrint(BCLog::NET, "waking up select()\n"); char buf[1]; if (write(wakeupPipe[1], buf, 1) != 1) { - LogPrint("net", "write to wakeupPipe failed\n"); + LogPrint(BCLog::NET, "write to wakeupPipe failed\n"); } #endif @@ -1747,7 +1748,7 @@ void CConnman::DumpAddresses() CAddrDB adb; adb.Write(addrman); - LogPrint("net", "Flushed %d addresses to peers.dat %dms\n", + LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart); } @@ -1949,7 +1950,7 @@ void CConnman::ThreadOpenConnections() int randsleep = GetRandInt(FEELER_SLEEP_WINDOW * 1000); if (!interruptNet.sleep_for(std::chrono::milliseconds(randsleep))) return; - LogPrint("net", "Making feeler connection to %s\n", addrConnect.ToString()); + LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToString()); } OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant, NULL, false, fFeeler); @@ -2369,9 +2370,7 @@ void Discover(boost::thread_group& threadGroup) void CConnman::SetNetworkActive(bool active) { - if (fDebug) { - LogPrint("net", "SetNetworkActive: %s\n", active); - } + LogPrint(BCLog::NET, "SetNetworkActive: %s\n", active); if (!active) { fNetworkActive = false; @@ -2463,7 +2462,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c SetBannedSetDirty(false); // no need to write down, just read data SweepBanned(); // sweep out unused entries - LogPrint("net", "Loaded %d banned node ips/subnets from banlist.dat %dms\n", + LogPrint(BCLog::NET, "Loaded %d banned node ips/subnets from banlist.dat %dms\n", banmap.size(), GetTimeMillis() - nStart); } else { LogPrintf("Invalid or missing banlist.dat; recreating\n"); @@ -2504,15 +2503,15 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c #ifndef WIN32 if (pipe(wakeupPipe) != 0) { wakeupPipe[0] = wakeupPipe[1] = -1; - LogPrint("net", "pipe() for wakeupPipe failed\n"); + LogPrint(BCLog::NET, "pipe() for wakeupPipe failed\n"); } else { int fFlags = fcntl(wakeupPipe[0], F_GETFL, 0); if (fcntl(wakeupPipe[0], F_SETFL, fFlags | O_NONBLOCK) == -1) { - LogPrint("net", "fcntl for O_NONBLOCK on wakeupPipe failed\n"); + LogPrint(BCLog::NET, "fcntl for O_NONBLOCK on wakeupPipe failed\n"); } fFlags = fcntl(wakeupPipe[1], F_GETFL, 0); if (fcntl(wakeupPipe[1], F_SETFL, fFlags | O_NONBLOCK) == -1) { - LogPrint("net", "fcntl for O_NONBLOCK on wakeupPipe failed\n"); + LogPrint(BCLog::NET, "fcntl for O_NONBLOCK on wakeupPipe failed\n"); } } #endif @@ -3126,10 +3125,11 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; - if (fLogIPs) - LogPrint("net", "Added connection to %s peer=%d\n", addrName, id); - else - LogPrint("net", "Added connection peer=%d\n", id); + if (fLogIPs) { + LogPrint(BCLog::NET, "Added connection to %s peer=%d\n", addrName, id); + } else { + LogPrint(BCLog::NET, "Added connection peer=%d\n", id); + } } CNode::~CNode() @@ -3168,7 +3168,7 @@ void CNode::AskFor(const CInv& inv, int64_t doubleRequestDelay) else nRequestTime = 0; - LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000), id); + LogPrint(BCLog::NET, "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000), id); // Make sure not to reuse time indexes to keep things in the same order int64_t nNow = GetTimeMicros() - 1000000; @@ -3204,7 +3204,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg, bool allowOpti { size_t nMessageSize = msg.data.size(); size_t nTotalSize = nMessageSize + CMessageHeader::HEADER_SIZE; - LogPrint("net", "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->id); + LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->id); std::vector serializedHeader; serializedHeader.reserve(CMessageHeader::HEADER_SIZE); diff --git a/src/net.h b/src/net.h index 57a8b07d7c66..48baf7a1045a 100644 --- a/src/net.h +++ b/src/net.h @@ -957,20 +957,20 @@ class CNode LOCK(cs_inventory); if (inv.type == MSG_TX) { if (!filterInventoryKnown.contains(inv.hash)) { - LogPrint("net", "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id); + LogPrint(BCLog::NET, "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id); setInventoryTxToSend.insert(inv.hash); } else { - LogPrint("net", "PushInventory -- filtered inv: %s peer=%d\n", inv.ToString(), id); + LogPrint(BCLog::NET, "PushInventory -- filtered inv: %s peer=%d\n", inv.ToString(), id); } } else if (inv.type == MSG_BLOCK) { - LogPrint("net", "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id); + LogPrint(BCLog::NET, "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id); vInventoryBlockToSend.push_back(inv.hash); } else { if (!filterInventoryKnown.contains(inv.hash)) { - LogPrint("net", "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id); + LogPrint(BCLog::NET, "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id); vInventoryOtherToSend.push_back(inv); } else { - LogPrint("net", "PushInventory -- filtered inv: %s peer=%d\n", inv.ToString(), id); + LogPrint(BCLog::NET, "PushInventory -- filtered inv: %s peer=%d\n", inv.ToString(), id); } } } diff --git a/src/net_processing.cpp b/src/net_processing.cpp index ca233f9f1a38..db39f78ca9ce 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -296,10 +296,11 @@ void PushNodeVersion(CNode *pnode, CConnman& connman, int64_t nTime) connman.PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, (uint64_t)nLocalNodeServices, nTime, addrYou, addrMe, nonce, strSubVersion, nNodeStartingHeight, ::fRelayTxes, mnauthChallenge)); - if (fLogIPs) - LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid); - else - LogPrint("net", "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid); + if (fLogIPs) { + LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), addrYou.ToString(), nodeid); + } else { + LogPrint(BCLog::NET, "send version message: version %d, blocks=%d, us=%s, peer=%d\n", PROTOCOL_VERSION, nNodeStartingHeight, addrMe.ToString(), nodeid); + } } void InitializeNode(CNode *pnode, CConnman& connman) { @@ -655,7 +656,7 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE unsigned int sz = GetSerializeSize(*tx, SER_NETWORK, CTransaction::CURRENT_VERSION); if (sz > MAX_STANDARD_TX_SIZE) { - LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); + LogPrint(BCLog::MEMPOOL, "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString()); return false; } @@ -667,7 +668,7 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE AddToCompactExtraTransactions(tx); - LogPrint("mempool", "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(), + LogPrint(BCLog::MEMPOOL, "stored orphan tx %s (mapsz %u outsz %u)\n", hash.ToString(), mapOrphanTransactions.size(), mapOrphanTransactionsByPrev.size()); return true; } @@ -703,7 +704,7 @@ void EraseOrphansFor(NodeId peer) nErased += EraseOrphanTx(maybeErase->second.tx->GetHash()); } } - if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx from peer=%d\n", nErased, peer); + if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx from peer=%d\n", nErased, peer); } @@ -730,7 +731,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans) } // Sweep again 5 minutes after the next entry that expires in order to batch the linear scan. nNextSweep = nMinExpTime + ORPHAN_TX_EXPIRE_INTERVAL; - if (nErased > 0) LogPrint("mempool", "Erased %d orphan tx due to expiration\n", nErased); + if (nErased > 0) LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx due to expiration\n", nErased); } while (mapOrphanTransactions.size() > nMaxOrphans) { @@ -829,7 +830,7 @@ void PeerLogicValidation::SyncTransaction(const CTransaction& tx, const CBlockIn BOOST_FOREACH(uint256 &orphanHash, vOrphanErase) { nErased += EraseOrphanTx(orphanHash); } - LogPrint("mempool", "Erased %d orphan tx included or conflicted by block\n", nErased); + LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased); } } @@ -870,7 +871,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std: if (state.fPreferHeaderAndIDs && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->pprev)) { - LogPrint("net", "%s sending header-and-ids %s to peer=%d\n", "PeerLogicValidation::NewPoWValidBlock", + LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", "PeerLogicValidation::NewPoWValidBlock", hashBlock.ToString(), pnode->id); connman->PushMessage(pnode, msgMaker.Make(NetMsgType::CMPCTBLOCK, *pcmpctblock)); state.pindexBestHeaderSent = pindex; @@ -1109,7 +1110,7 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus // never disconnect whitelisted nodes if (send && connman.OutboundTargetReached(true) && ( ((pindexBestHeader != NULL) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) { - LogPrint("net", "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId()); + LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId()); //disconnect node pfrom->fDisconnect = true; @@ -1265,7 +1266,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } if (!push && inv.type == MSG_GOVERNANCE_OBJECT) { - LogPrint("net", "ProcessGetData -- MSG_GOVERNANCE_OBJECT: inv = %s\n", inv.ToString()); + LogPrint(BCLog::NET, "ProcessGetData -- MSG_GOVERNANCE_OBJECT: inv = %s\n", inv.ToString()); CDataStream ss(SER_NETWORK, pfrom->GetSendVersion()); bool topush = false; { @@ -1276,7 +1277,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } } - LogPrint("net", "ProcessGetData -- MSG_GOVERNANCE_OBJECT: topush = %d, inv = %s\n", topush, inv.ToString()); + LogPrint(BCLog::NET, "ProcessGetData -- MSG_GOVERNANCE_OBJECT: topush = %d, inv = %s\n", topush, inv.ToString()); if(topush) { connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNGOVERNANCEOBJECT, ss)); push = true; @@ -1295,7 +1296,7 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } if(topush) { - LogPrint("net", "ProcessGetData -- pushing: inv = %s\n", inv.ToString()); + LogPrint(BCLog::NET, "ProcessGetData -- pushing: inv = %s\n", inv.ToString()); connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNGOVERNANCEOBJECTVOTE, ss)); push = true; } @@ -1409,8 +1410,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, const std::atomic& interruptMsgProc) { - LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); - + LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); if (IsArgSet("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 0)) == 0) { LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n"); @@ -1442,7 +1442,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } } catch (const std::ios_base::failure&) { // Avoid feedback loops by preventing reject messages from triggering a new reject message. - LogPrint("net", "Unparseable reject message received\n"); + LogPrint(BCLog::NET, "Unparseable reject message received\n"); } if (strMsg == NetMsgType::BLOCK) { @@ -1453,14 +1453,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr Misbehaving(pfrom->id, 1); } - if (fDebug) { + if (LogAcceptCategory(BCLog::NET)) { std::ostringstream ss; ss << strMsg << " code " << itostr(ccode) << ": " << strReason; if (strMsg == NetMsgType::BLOCK || strMsg == NetMsgType::TX) { ss << ": hash " << hash.ToString(); } - LogPrint("net", "Reject %s\n", SanitizeString(ss.str())); + LogPrint(BCLog::NET, "Reject %s\n", SanitizeString(ss.str())); } } @@ -1497,7 +1497,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } if (pfrom->nServicesExpected & ~nServices) { - LogPrint("net", "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, nServices, pfrom->nServicesExpected); + LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, nServices, pfrom->nServicesExpected); connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD, strprintf("Expected to offer services %08x", pfrom->nServicesExpected))); pfrom->fDisconnect = true; @@ -1596,11 +1596,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr FastRandomContext insecure_rand; if (addr.IsRoutable()) { - LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString()); + LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString()); pfrom->PushAddress(addr, insecure_rand); } else if (IsPeerAddrLocalGood(pfrom)) { addr.SetIP(addrMe); - LogPrint("net", "ProcessMessages: advertising address %s\n", addr.ToString()); + LogPrint(BCLog::NET, "ProcessMessages: advertising address %s\n", addr.ToString()); pfrom->PushAddress(addr, insecure_rand); } } @@ -1825,7 +1825,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr const CInv &inv = vInv[nInv]; if(!inv.IsKnownType()) { - LogPrint("net", "got inv of unknown type %d: %s peer=%d\n", inv.type, inv.hash.ToString(), pfrom->id); + LogPrint(BCLog::NET, "got inv of unknown type %d: %s peer=%d\n", inv.type, inv.hash.ToString(), pfrom->id); continue; } @@ -1833,7 +1833,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return true; bool fAlreadyHave = AlreadyHave(inv); - LogPrint("net", "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id); + LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id); if (inv.type == MSG_BLOCK) { UpdateBlockAvailability(pfrom->GetId(), inv.hash); @@ -1861,7 +1861,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // we now only provide a getheaders response here. When we receive the headers, we will // then ask for the blocks we need. connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash)); - LogPrint("net", "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id); + LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id); } } else @@ -1872,7 +1872,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->AddInventoryKnown(inv); if (fBlocksOnly) { - LogPrint("net", "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), + LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), pfrom->id); } else if (!fAlreadyHave) { bool allowWhileInIBD = allowWhileInIBDObjs.count(inv.type); @@ -1912,11 +1912,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return error("message getdata size() = %u", vInv.size()); } - if (fDebug || (vInv.size() != 1)) - LogPrint("net", "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->id); + LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->id); - if ((fDebug && vInv.size() > 0) || (vInv.size() == 1)) - LogPrint("net", "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id); + if (vInv.size() > 0) { + LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id); + } pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); ProcessGetData(pfrom, chainparams.GetConsensus(), connman, interruptMsgProc); @@ -1955,12 +1955,12 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (pindex) pindex = chainActive.Next(pindex); int nLimit = 500; - LogPrint("net", "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->id); + LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->id); for (; pindex; pindex = chainActive.Next(pindex)) { if (pindex->GetBlockHash() == hashStop) { - LogPrint("net", " getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); + LogPrint(BCLog::NET, " getblocks stopping at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); break; } // If pruning, don't inv blocks unless we have on disk and are likely to still have @@ -1968,7 +1968,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr const int nPrunedBlocksLikelyToHave = MIN_BLOCKS_TO_KEEP - 3600 / chainparams.GetConsensus().nPowTargetSpacing; if (fPruneMode && (!(pindex->nStatus & BLOCK_HAVE_DATA) || pindex->nHeight <= chainActive.Tip()->nHeight - nPrunedBlocksLikelyToHave)) { - LogPrint("net", " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); + LogPrint(BCLog::NET, " getblocks stopping, pruned or too old block at %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); break; } pfrom->PushInventory(CInv(MSG_BLOCK, pindex->GetBlockHash())); @@ -1976,7 +1976,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr { // When this block is requested, we'll send an inv that'll // trigger the peer to getblocks the next batch of inventory. - LogPrint("net", " getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); + LogPrint(BCLog::NET, " getblocks stopping at limit %d %s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); pfrom->hashContinue = pindex->GetBlockHash(); break; } @@ -2017,7 +2017,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // might maliciously send lots of getblocktxn requests to trigger // expensive disk reads, because it will require the peer to // actually receive all the data read from disk over the network. - LogPrint("net", "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->id, MAX_BLOCKTXN_DEPTH); + LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->id, MAX_BLOCKTXN_DEPTH); CInv inv; inv.type = MSG_BLOCK; inv.hash = req.blockhash; @@ -2042,7 +2042,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); if (IsInitialBlockDownload() && !pfrom->fWhitelisted) { - LogPrint("net", "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->id); + LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->id); return true; } @@ -2072,7 +2072,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end std::vector vHeaders; int nLimit = MAX_HEADERS_RESULTS; - LogPrint("net", "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->id); + LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->id); for (; pindex; pindex = chainActive.Next(pindex)) { vHeaders.push_back(pindex->GetBlockHeader()); @@ -2102,7 +2102,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off if (!fRelayTxes && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))) { - LogPrint("net", "transaction sent in violation of protocol peer=%d\n", pfrom->id); + LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->id); return true; } @@ -2145,7 +2145,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Process custom logic, no matter if tx will be accepted to mempool later or not if (nInvType == MSG_TXLOCK_REQUEST || fCanAutoLock) { if(!instantsend.ProcessTxLockRequest(txLockRequest, connman)) { - LogPrint("instantsend", "TXLOCKREQUEST -- failed %s\n", txLockRequest.GetHash().ToString()); + LogPrint(BCLog::INSTANTSEND, "TXLOCKREQUEST -- failed %s\n", txLockRequest.GetHash().ToString()); // Should not really happen for "fCanAutoLock == true" but just in case: if (!fCanAutoLock) { // Fail only for "true" IS here @@ -2157,25 +2157,25 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } else if (nInvType == MSG_DSTX) { uint256 hashTx = tx.GetHash(); if(CPrivateSend::GetDSTX(hashTx)) { - LogPrint("privatesend", "DSTX -- Already have %s, skipping...\n", hashTx.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSTX -- Already have %s, skipping...\n", hashTx.ToString()); return true; // not an error } 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()); + LogPrint(BCLog::PRIVATESEND, "DSTX -- Can't find masternode %s to verify %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString()); return false; } if (!mmetaman.GetMetaInfo(dmn->proTxHash)->IsValidForMixingTxes()) { - LogPrint("privatesend", "DSTX -- Masternode %s is sending too many transactions %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString()); + LogPrint(BCLog::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(dmn->pdmnState->pubKeyOperator)) { - LogPrint("privatesend", "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString()); return false; } @@ -2210,7 +2210,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->nLastTXTime = GetTime(); - LogPrint("mempool", "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n", + LogPrint(BCLog::MEMPOOL, "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n", pfrom->id, tx.GetHash().ToString(), mempool.size(), mempool.DynamicMemoryUsage() / 1000); @@ -2240,7 +2240,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (setMisbehaving.count(fromPeer)) continue; if (AcceptToMemoryPool(mempool, stateDummy, porphanTx, true, &fMissingInputs2)) { - LogPrint("mempool", " accepted orphan tx %s\n", orphanHash.ToString()); + LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString()); connman.RelayTransaction(orphanTx); for (unsigned int i = 0; i < orphanTx.vout.size(); i++) { vWorkQueue.emplace_back(orphanHash, i); @@ -2255,11 +2255,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Punish peer that gave us an invalid orphan tx Misbehaving(fromPeer, nDos); setMisbehaving.insert(fromPeer); - LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString()); + LogPrint(BCLog::MEMPOOL, " invalid orphan tx %s\n", orphanHash.ToString()); } // Has inputs but not accepted to mempool // Probably non-standard or insufficient fee - LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString()); + LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString()); vEraseQueue.push_back(orphanHash); if (!stateDummy.CorruptionPossible()) { assert(recentRejects); @@ -2293,10 +2293,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // DoS prevention: do not allow mapOrphanTransactions to grow unbounded unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx); - if (nEvicted > 0) - LogPrint("mempool", "mapOrphan overflow, removed %u tx\n", nEvicted); + if (nEvicted > 0) { + LogPrint(BCLog::MEMPOOL, "mapOrphan overflow, removed %u tx\n", nEvicted); + } } else { - LogPrint("mempool", "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString()); + LogPrint(BCLog::MEMPOOL, "not keeping orphan with rejected parents %s\n",tx.GetHash().ToString()); // We will continue to reject this tx since it has rejected // parents so avoid re-requesting it from other peers. recentRejects->insert(tx.GetHash()); @@ -2345,7 +2346,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr int nDoS = 0; if (state.IsInvalid(nDoS)) { - LogPrint("mempoolrej", "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(), + LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state)); if (state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P @@ -2445,7 +2446,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr (*queuedBlockIt)->partialBlock.reset(new PartiallyDownloadedBlock(&mempool)); else { // The block was already in flight using compact blocks from the same peer - LogPrint("net", "Peer sent us compact block we were already syncing!\n"); + LogPrint(BCLog::NET, "Peer sent us compact block we were already syncing!\n"); return true; } } @@ -2560,7 +2561,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr std::map::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash); if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock || it->second.first != pfrom->GetId()) { - LogPrint("net", "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->id); + LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->id); return true; } @@ -2653,7 +2654,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) { nodestate->nUnconnectingHeaders++; connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256())); - LogPrint("net", "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n", + LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n", headers[0].GetHash().ToString(), headers[0].hashPrevBlock.ToString(), pindexBestHeader->nHeight, @@ -2695,7 +2696,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); CNodeState *nodestate = State(pfrom->GetId()); if (nodestate->nUnconnectingHeaders > 0) { - LogPrint("net", "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders); + LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders); } nodestate->nUnconnectingHeaders = 0; @@ -2706,7 +2707,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Headers message had its maximum size; the peer may have more headers. // TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue // from there instead. - LogPrint("net", "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->id, pfrom->nStartingHeight); + LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->id, pfrom->nStartingHeight); connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256())); } @@ -2730,7 +2731,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // the main chain -- this shouldn't really happen. Bail out on the // direct fetch and rely on parallel download instead. if (!chainActive.Contains(pindexWalk)) { - LogPrint("net", "Large reorg, won't direct fetch to %s (%d)\n", + LogPrint(BCLog::NET, "Large reorg, won't direct fetch to %s (%d)\n", pindexLast->GetBlockHash().ToString(), pindexLast->nHeight); } else { @@ -2743,11 +2744,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex); - LogPrint("net", "Requesting block %s from peer=%d\n", + LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n", pindex->GetBlockHash().ToString(), pfrom->id); } if (vGetData.size() > 1) { - LogPrint("net", "Downloading blocks toward %s (%d) via headers direct fetch\n", + LogPrint(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n", pindexLast->GetBlockHash().ToString(), pindexLast->nHeight); } if (vGetData.size() > 0) { @@ -2767,7 +2768,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr std::shared_ptr pblock = std::make_shared(); vRecv >> *pblock; - LogPrint("net", "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->id); + LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->id); // Process all blocks from whitelisted peers, even if not requested, // unless we're still syncing with the network. @@ -2799,14 +2800,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Making nodes which are behind NAT and can only make outgoing connections ignore // the getaddr message mitigates the attack. if (!pfrom->fInbound) { - LogPrint("net", "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->id); + LogPrint(BCLog::NET, "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->id); return true; } // Only send one GetAddr response per connection to reduce resource waste // and discourage addr stamping of INV announcements. if (pfrom->fSentAddr) { - LogPrint("net", "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->id); + LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->id); return true; } pfrom->fSentAddr = true; @@ -2823,14 +2824,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr { if (!(pfrom->GetLocalServices() & NODE_BLOOM) && !pfrom->fWhitelisted) { - LogPrint("net", "mempool request with bloom filters disabled, disconnect peer=%d\n", pfrom->GetId()); + LogPrint(BCLog::NET, "mempool request with bloom filters disabled, disconnect peer=%d\n", pfrom->GetId()); pfrom->fDisconnect = true; return true; } if (connman.OutboundTargetReached(false) && !pfrom->fWhitelisted) { - LogPrint("net", "mempool request with bandwidth limit reached, disconnect peer=%d\n", pfrom->GetId()); + LogPrint(BCLog::NET, "mempool request with bandwidth limit reached, disconnect peer=%d\n", pfrom->GetId()); pfrom->fDisconnect = true; return true; } @@ -2906,7 +2907,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } if (!(sProblem.empty())) { - LogPrint("net", "pong peer=%d: %s, %x expected, %x received, %u bytes\n", + LogPrint(BCLog::NET, "pong peer=%d: %s, %x expected, %x received, %u bytes\n", pfrom->id, sProblem, pfrom->nPingNonceSent, @@ -3019,7 +3020,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (BuildSimplifiedMNListDiff(cmd.baseBlockHash, cmd.blockHash, mnListDiff, strError)) { connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNLISTDIFF, mnListDiff)); } else { - LogPrint("net", "getmnlistdiff failed for baseBlockHash=%s, blockHash=%s. error=%s\n", cmd.baseBlockHash.ToString(), cmd.blockHash.ToString(), strError); + LogPrint(BCLog::NET, "getmnlistdiff failed for baseBlockHash=%s, blockHash=%s. error=%s\n", cmd.baseBlockHash.ToString(), cmd.blockHash.ToString(), strError); Misbehaving(pfrom->id, 1); } } @@ -3029,7 +3030,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // we have never requested this LOCK(cs_main); Misbehaving(pfrom->id, 100); - LogPrint("net", "received not-requested mnlistdiff. peer=%d\n", pfrom->id); + LogPrint(BCLog::NET, "received not-requested mnlistdiff. peer=%d\n", pfrom->id); } @@ -3070,7 +3071,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr else { // Ignore unknown commands for extensibility - LogPrint("net", "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id); + LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id); } } @@ -3345,7 +3346,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr got back an empty response. */ if (pindexStart->pprev) pindexStart = pindexStart->pprev; - LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight); + LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight); connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256())); } } @@ -3438,7 +3439,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr if (vHeaders.size() == 1 && state.fPreferHeaderAndIDs) { // We only send up to 1 block as header-and-ids, as otherwise // probably means we're doing an initial-ish-sync or they're slow - LogPrint("net", "%s sending header-and-ids %s to peer=%d\n", __func__, + LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", __func__, vHeaders.front().GetHash().ToString(), pto->id); bool fGotBlockFromCache = false; @@ -3459,12 +3460,12 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr state.pindexBestHeaderSent = pBestIndex; } else if (state.fPreferHeaders) { if (vHeaders.size() > 1) { - LogPrint("net", "%s: %u headers, range (%s, %s), to peer=%d\n", __func__, + LogPrint(BCLog::NET, "%s: %u headers, range (%s, %s), to peer=%d\n", __func__, vHeaders.size(), vHeaders.front().GetHash().ToString(), vHeaders.back().GetHash().ToString(), pto->id); } else { - LogPrint("net", "%s: sending header %s to peer=%d\n", __func__, + LogPrint(BCLog::NET, "%s: sending header %s to peer=%d\n", __func__, vHeaders.front().GetHash().ToString(), pto->id); } connman.PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders)); @@ -3486,14 +3487,14 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr // This should be very rare and could be optimized out. // Just log for now. if (chainActive[pindex->nHeight] != pindex) { - LogPrint("net", "Announcing block %s not on main chain (tip=%s)\n", + LogPrint(BCLog::NET, "Announcing block %s not on main chain (tip=%s)\n", hashToAnnounce.ToString(), chainActive.Tip()->GetBlockHash().ToString()); } // If the peer's chain has this block, don't inv it back. if (!PeerHasHeader(&state, pindex)) { pto->PushInventory(CInv(MSG_BLOCK, hashToAnnounce)); - LogPrint("net", "%s: sending inv peer=%d hash=%s\n", __func__, + LogPrint(BCLog::NET, "%s: sending inv peer=%d hash=%s\n", __func__, pto->id, hashToAnnounce.ToString()); } } @@ -3552,10 +3553,10 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr } pto->filterInventoryKnown.insert(hash); - LogPrint("net", "SendMessages -- queued inv: %s index=%d peer=%d\n", inv.ToString(), vInv.size(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- queued inv: %s index=%d peer=%d\n", inv.ToString(), vInv.size(), pto->id); vInv.push_back(inv); if (vInv.size() == MAX_INV_SZ) { - LogPrint("net", "SendMessages -- pushing inv's: count=%d peer=%d\n", vInv.size(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- pushing inv's: count=%d peer=%d\n", vInv.size(), pto->id); connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv)); vInv.clear(); } @@ -3707,13 +3708,13 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr BOOST_FOREACH(const CBlockIndex *pindex, vToDownload) { vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); - LogPrint("net", "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), + LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), pindex->nHeight, pto->id); } if (state.nBlocksInFlight == 0 && staller != -1) { if (State(staller)->nStallingSince == 0) { State(staller)->nStallingSince = nNow; - LogPrint("net", "Stall started peer=%d\n", staller); + LogPrint(BCLog::NET, "Stall started peer=%d\n", staller); } } } @@ -3728,17 +3729,17 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr const CInv& inv = it->second; if (!AlreadyHave(inv)) { - LogPrint("net", "SendMessages -- GETDATA -- requesting inv = %s peer=%d\n", inv.ToString(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- GETDATA -- requesting inv = %s peer=%d\n", inv.ToString(), pto->id); vGetData.push_back(inv); if (vGetData.size() >= 1000) { connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData)); - LogPrint("net", "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->id); vGetData.clear(); } } else { //If we're not going to ask, don't expect a response. - LogPrint("net", "SendMessages -- GETDATA -- already have inv = %s peer=%d\n", inv.ToString(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- GETDATA -- already have inv = %s peer=%d\n", inv.ToString(), pto->id); pto->setAskFor.erase(inv.hash); } ++it; @@ -3746,7 +3747,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr pto->vecAskFor.erase(pto->vecAskFor.begin(), it); if (!vGetData.empty()) { connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData)); - LogPrint("net", "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->id); } } diff --git a/src/netbase.cpp b/src/netbase.cpp index 90a087f7e8d7..2739520b6b45 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -281,7 +281,7 @@ std::string Socks5ErrorString(int err) static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket) { IntrRecvError recvr; - LogPrint("net", "SOCKS5 connecting %s\n", strDest); + LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest); if (strDest.size() > 255) { CloseSocket(hSocket); return error("Hostname too long"); @@ -327,7 +327,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Error sending authentication to proxy"); } - LogPrint("proxy", "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); + LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password); char pchRetA[2]; if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) { CloseSocket(hSocket); @@ -409,7 +409,7 @@ static bool Socks5(const std::string& strDest, int port, const ProxyCredentials CloseSocket(hSocket); return error("Error reading from proxy"); } - LogPrint("net", "SOCKS5 connected %s\n", strDest); + LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest); return true; } @@ -458,7 +458,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout); if (nRet == 0) { - LogPrint("net", "connection to %s timeout\n", addrConnect.ToString()); + LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString()); CloseSocket(hSocket); return false; } diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index a3c13bb7e9bb..75e3ce5d0ccb 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -164,7 +164,7 @@ double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal, } } - LogPrint("estimatefee", "%3d: For conf success %s %4.2f need feerate %s: %12.5g from buckets %8g - %8g Cur Bucket stats %6.2f%% %8.1f/(%.1f+%d mempool)\n", + LogPrint(BCLog::ESTIMATEFEE, "%3d: For conf success %s %4.2f need feerate %s: %12.5g from buckets %8g - %8g Cur Bucket stats %6.2f%% %8.1f/(%.1f+%d mempool)\n", confTarget, requireGreater ? ">" : "<", successBreakPoint, requireGreater ? ">" : "<", median, buckets[minBucket], buckets[maxBucket], 100 * nConf / (totalNum + extraNum), nConf, totalNum, extraNum); @@ -240,7 +240,7 @@ void TxConfirmStats::Read(CAutoFile& filein) for (unsigned int i = 0; i < buckets.size(); i++) bucketMap[buckets[i]] = i; - LogPrint("estimatefee", "Reading estimates: %u buckets counting confirms up to %u blocks\n", + LogPrint(BCLog::ESTIMATEFEE, "Reading estimates: %u buckets counting confirms up to %u blocks\n", numBuckets, maxConfirms); } @@ -259,24 +259,26 @@ void TxConfirmStats::removeTx(unsigned int entryHeight, unsigned int nBestSeenHe if (nBestSeenHeight == 0) // the BlockPolicyEstimator hasn't seen any blocks yet blocksAgo = 0; if (blocksAgo < 0) { - LogPrint("estimatefee", "Blockpolicy error, blocks ago is negative for mempool tx\n"); + LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error, blocks ago is negative for mempool tx\n"); return; //This can't happen because we call this with our best seen height, no entries can have higher } if (blocksAgo >= (int)unconfTxs.size()) { - if (oldUnconfTxs[bucketindex] > 0) + if (oldUnconfTxs[bucketindex] > 0) { oldUnconfTxs[bucketindex]--; - else - LogPrint("estimatefee", "Blockpolicy error, mempool tx removed from >25 blocks,bucketIndex=%u already\n", + } else { + LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error, mempool tx removed from >25 blocks,bucketIndex=%u already\n", bucketindex); + } } else { unsigned int blockIndex = entryHeight % unconfTxs.size(); - if (unconfTxs[blockIndex][bucketindex] > 0) + if (unconfTxs[blockIndex][bucketindex] > 0) { unconfTxs[blockIndex][bucketindex]--; - else - LogPrint("estimatefee", "Blockpolicy error, mempool tx removed from blockIndex=%u,bucketIndex=%u already\n", + } else { + LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error, mempool tx removed from blockIndex=%u,bucketIndex=%u already\n", blockIndex, bucketindex); + } } } @@ -315,7 +317,7 @@ void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, boo unsigned int txHeight = entry.GetHeight(); uint256 hash = entry.GetTx().GetHash(); if (mapMemPoolTxs.count(hash)) { - LogPrint("estimatefee", "Blockpolicy error mempool tx %s already being tracked\n", hash.ToString()); + LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error mempool tx %s already being tracked\n", hash.ToString()); return; } @@ -356,7 +358,7 @@ bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxM if (blocksToConfirm <= 0) { // This can't happen because we don't process transactions from a block with a height // lower than our greatest seen height - LogPrint("estimatefee", "Blockpolicy error Transaction had negative blocksToConfirm\n"); + LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error Transaction had negative blocksToConfirm\n"); return false; } @@ -397,7 +399,7 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight, // Update all exponential averages with the current block state feeStats.UpdateMovingAverages(); - LogPrint("estimatefee", "Blockpolicy after updating estimates for %u of %u txs in block, since last block %u of %u tracked, new mempool map size %u\n", + LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy after updating estimates for %u of %u txs in block, since last block %u of %u tracked, new mempool map size %u\n", countedTxs, entries.size(), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size()); trackedTxs = 0; diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index 49076ec769fb..c892136b3563 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -37,7 +37,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& if (strCommand == NetMsgType::DSQUEUE) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint("privatesend", "DSQUEUE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- 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", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -52,13 +52,13 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& // process every dsq only once for (const auto& q : vecPrivateSendQueue) { if (q == dsq) { - // LogPrint("privatesend", "DSQUEUE -- %s seen\n", dsq.ToString()); + // LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- %s seen\n", dsq.ToString()); return; } } } // cs_vecqueue - LogPrint("privatesend", "DSQUEUE -- %s new\n", dsq.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- %s new\n", dsq.ToString()); if (dsq.IsExpired()) return; @@ -78,7 +78,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& for (auto& session : deqSessions) { 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()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- PrivateSend queue (%s) is ready on masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); session.SubmitDenominate(connman); return; } @@ -91,23 +91,23 @@ 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", dmn->pdmnState->ToString()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->ToString()); return; } } 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()); + LogPrint(BCLog::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 (nLastDsq != 0 && nThreshold > mmetaman.GetDsqCount()) { - LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->proTxHash.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->proTxHash.ToString()); return; } mmetaman.AllowMixing(dmn->proTxHash); - LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); for (auto& session : deqSessions) { CDeterministicMNCPtr mnMixing; if (session.GetMixingMasternodeInfo(mnMixing) && mnMixing->collateralOutpoint == dsq.masternodeOutpoint) { @@ -137,7 +137,7 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& if (strCommand == NetMsgType::DSSTATUSUPDATE) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint("privatesend", "DSSTATUSUPDATE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- 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", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -156,30 +156,30 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& vRecv >> nMsgSessionID >> nMsgState >> nMsgEntriesCount >> nMsgStatusUpdate >> nMsgMessageID; if (nMsgState < POOL_STATE_MIN || nMsgState > POOL_STATE_MAX) { - LogPrint("privatesend", "DSSTATUSUPDATE -- nMsgState is out of bounds: %d\n", nMsgState); + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- nMsgState is out of bounds: %d\n", nMsgState); return; } if (nMsgStatusUpdate < STATUS_REJECTED || nMsgStatusUpdate > STATUS_ACCEPTED) { - LogPrint("privatesend", "DSSTATUSUPDATE -- nMsgStatusUpdate is out of bounds: %d\n", nMsgStatusUpdate); + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- nMsgStatusUpdate is out of bounds: %d\n", nMsgStatusUpdate); return; } if (nMsgMessageID < MSG_POOL_MIN || nMsgMessageID > MSG_POOL_MAX) { - LogPrint("privatesend", "DSSTATUSUPDATE -- nMsgMessageID is out of bounds: %d\n", nMsgMessageID); + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- nMsgMessageID is out of bounds: %d\n", nMsgMessageID); return; } - LogPrint("privatesend", "DSSTATUSUPDATE -- nMsgSessionID %d nMsgState: %d nEntriesCount: %d nMsgStatusUpdate: %d nMsgMessageID %d (%s)\n", + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- nMsgSessionID %d nMsgState: %d nEntriesCount: %d nMsgStatusUpdate: %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgState, nEntriesCount, nMsgStatusUpdate, nMsgMessageID, CPrivateSend::GetMessageByID(PoolMessage(nMsgMessageID))); if (!CheckPoolStateUpdate(PoolState(nMsgState), nMsgEntriesCount, PoolStatusUpdate(nMsgStatusUpdate), PoolMessage(nMsgMessageID), nMsgSessionID)) { - LogPrint("privatesend", "DSSTATUSUPDATE -- CheckPoolStateUpdate failed\n"); + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- CheckPoolStateUpdate failed\n"); } } else if (strCommand == NetMsgType::DSFINALTX) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint("privatesend", "DSFINALTX -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSFINALTX -- 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", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -195,25 +195,25 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& CTransaction txNew(deserialize, vRecv); if (nSessionID != nMsgSessionID) { - LogPrint("privatesend", "DSFINALTX -- message doesn't match current PrivateSend session: nSessionID: %d nMsgSessionID: %d\n", nSessionID, nMsgSessionID); + LogPrint(BCLog::PRIVATESEND, "DSFINALTX -- message doesn't match current PrivateSend session: nSessionID: %d nMsgSessionID: %d\n", nSessionID, nMsgSessionID); return; } - LogPrint("privatesend", "DSFINALTX -- txNew %s", txNew.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSFINALTX -- txNew %s", txNew.ToString()); //check to see if input is spent already? (and probably not confirmed) SignFinalTransaction(txNew, pfrom, connman); } else if (strCommand == NetMsgType::DSCOMPLETE) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint("privatesend", "DSCOMPLETE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- 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", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } 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()); + LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- message doesn't match current Masternode: infoMixingMasternode=%s addr=%s\n", mixingMasternode->pdmnState->addr.ToString(), pfrom->addr.ToString()); return; } @@ -222,16 +222,16 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& vRecv >> nMsgSessionID >> nMsgMessageID; if (nMsgMessageID < MSG_POOL_MIN || nMsgMessageID > MSG_POOL_MAX) { - LogPrint("privatesend", "DSCOMPLETE -- nMsgMessageID is out of bounds: %d\n", nMsgMessageID); + LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- nMsgMessageID is out of bounds: %d\n", nMsgMessageID); return; } if (nSessionID != nMsgSessionID) { - LogPrint("privatesend", "DSCOMPLETE -- message doesn't match current PrivateSend session: nSessionID: %d nMsgSessionID: %d\n", nSessionID, nMsgSessionID); + LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- message doesn't match current PrivateSend session: nSessionID: %d nMsgSessionID: %d\n", nSessionID, nMsgSessionID); return; } - LogPrint("privatesend", "DSCOMPLETE -- nMsgSessionID %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgMessageID, CPrivateSend::GetMessageByID(PoolMessage(nMsgMessageID))); + LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- nMsgSessionID %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgMessageID, CPrivateSend::GetMessageByID(PoolMessage(nMsgMessageID))); CompletedTransaction(PoolMessage(nMsgMessageID)); } @@ -396,7 +396,7 @@ void CPrivateSendClientSession::CheckPool() { // reset if we're here for 10 seconds if ((nState == POOL_STATE_ERROR || nState == POOL_STATE_SUCCESS) && GetTime() - nTimeLastSuccessfulStep >= 10) { - LogPrint("privatesend", "CPrivateSendClientSession::CheckPool -- timeout, RESETTING\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CheckPool -- timeout, RESETTING\n"); UnlockCoins(); if (nState == POOL_STATE_ERROR) { keyHolderStorage.ReturnAll(); @@ -417,11 +417,11 @@ bool CPrivateSendClientSession::CheckTimeout() // catching hanging sessions switch (nState) { case POOL_STATE_ERROR: - LogPrint("privatesend", "CPrivateSendClientSession::CheckTimeout -- Pool error -- Running CheckPool\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CheckTimeout -- Pool error -- Running CheckPool\n"); CheckPool(); break; case POOL_STATE_SUCCESS: - LogPrint("privatesend", "CPrivateSendClientSession::CheckTimeout -- Pool success -- Running CheckPool\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CheckTimeout -- Pool success -- Running CheckPool\n"); CheckPool(); break; default: @@ -435,7 +435,7 @@ bool CPrivateSendClientSession::CheckTimeout() if (nState == POOL_STATE_IDLE || !fTimeout) return false; - LogPrint("privatesend", "CPrivateSendClientSession::CheckTimeout -- %s timed out (%ds) -- resetting\n", + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CheckTimeout -- %s timed out (%ds) -- resetting\n", (nState == POOL_STATE_SIGNING) ? "Signing" : "Session", nTimeout); UnlockCoins(); keyHolderStorage.ReturnAll(); @@ -647,14 +647,14 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr const CKeyStore& keystore = *pwalletMain; - LogPrint("privatesend", "CPrivateSendClientSession::SignFinalTransaction -- Signing my input %i\n", nMyInputIndex); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::SignFinalTransaction -- Signing my input %i\n", nMyInputIndex); if (!SignSignature(keystore, prevPubKey, finalMutableTransaction, nMyInputIndex, int(SIGHASH_ALL | SIGHASH_ANYONECANPAY))) { // changes scriptSig - LogPrint("privatesend", "CPrivateSendClientSession::SignFinalTransaction -- Unable to sign my own transaction!\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::SignFinalTransaction -- Unable to sign my own transaction!\n"); // not sure what to do here, it will timeout...? } sigs.push_back(finalMutableTransaction.vin[nMyInputIndex]); - LogPrint("privatesend", "CPrivateSendClientSession::SignFinalTransaction -- nMyInputIndex: %d, sigs.size(): %d, scriptSig=%s\n", nMyInputIndex, (int)sigs.size(), ScriptToAsmStr(finalMutableTransaction.vin[nMyInputIndex].scriptSig)); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::SignFinalTransaction -- nMyInputIndex: %d, sigs.size(): %d, scriptSig=%s\n", nMyInputIndex, (int)sigs.size(), ScriptToAsmStr(finalMutableTransaction.vin[nMyInputIndex].scriptSig)); } } } @@ -726,7 +726,7 @@ bool CPrivateSendClientManager::WaitForAnotherBlock() bool CPrivateSendClientManager::CheckAutomaticBackup() { if (!pwalletMain) { - LogPrint("privatesend", "CPrivateSendClientManager::CheckAutomaticBackup -- Wallet is not initialized, no mixing available.\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Wallet is not initialized, no mixing available.\n"); strAutoDenomResult = _("Wallet is not initialized") + ", " + _("no mixing available."); fEnablePrivateSend = false; // no mixing return false; @@ -734,7 +734,7 @@ bool CPrivateSendClientManager::CheckAutomaticBackup() switch (nWalletBackups) { case 0: - LogPrint("privatesend", "CPrivateSendClientManager::CheckAutomaticBackup -- Automatic backups disabled, no mixing available.\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Automatic backups disabled, no mixing available.\n"); strAutoDenomResult = _("Automatic backups disabled") + ", " + _("no mixing available."); fEnablePrivateSend = false; // stop mixing pwalletMain->nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup" @@ -743,32 +743,32 @@ bool CPrivateSendClientManager::CheckAutomaticBackup() // Automatic backup failed, nothing else we can do until user fixes the issue manually. // There is no way to bring user attention in daemon mode so we just update status and // keep spamming if debug is on. - LogPrint("privatesend", "CPrivateSendClientManager::CheckAutomaticBackup -- ERROR! Failed to create automatic backup.\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- ERROR! Failed to create automatic backup.\n"); strAutoDenomResult = _("ERROR! Failed to create automatic backup") + ", " + _("see debug.log for details."); return false; case -2: // We were able to create automatic backup but keypool was not replenished because wallet is locked. // There is no way to bring user attention in daemon mode so we just update status and // keep spamming if debug is on. - LogPrint("privatesend", "CPrivateSendClientManager::CheckAutomaticBackup -- WARNING! Failed to create replenish keypool, please unlock your wallet to do so.\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- WARNING! Failed to create replenish keypool, please unlock your wallet to do so.\n"); strAutoDenomResult = _("WARNING! Failed to replenish keypool, please unlock your wallet to do so.") + ", " + _("see debug.log for details."); return false; } if (pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_STOP) { // We should never get here via mixing itself but probably smth else is still actively using keypool - LogPrint("privatesend", "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d, no mixing available.\n", pwalletMain->nKeysLeftSinceAutoBackup); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d, no mixing available.\n", pwalletMain->nKeysLeftSinceAutoBackup); strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + ", " + _("no mixing available."), pwalletMain->nKeysLeftSinceAutoBackup); // It's getting really dangerous, stop mixing fEnablePrivateSend = false; return false; } else if (pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { // Low number of keys left but it's still more or less safe to continue - LogPrint("privatesend", "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d\n", pwalletMain->nKeysLeftSinceAutoBackup); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d\n", pwalletMain->nKeysLeftSinceAutoBackup); strAutoDenomResult = strprintf(_("Very low number of keys left: %d"), pwalletMain->nKeysLeftSinceAutoBackup); if (fCreateAutoBackups) { - LogPrint("privatesend", "CPrivateSendClientManager::CheckAutomaticBackup -- Trying to create new backup.\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Trying to create new backup.\n"); std::string warningString; std::string errorString; @@ -790,7 +790,7 @@ bool CPrivateSendClientManager::CheckAutomaticBackup() } } - LogPrint("privatesend", "CPrivateSendClientManager::CheckAutomaticBackup -- Keys left since latest backup: %d\n", pwalletMain->nKeysLeftSinceAutoBackup); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Keys left since latest backup: %d\n", pwalletMain->nKeysLeftSinceAutoBackup); return true; } @@ -835,7 +835,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool } if (deterministicMNManager->GetListAtChainTip().GetValidMNsCount() == 0) { - LogPrint("privatesend", "CPrivateSendClientSession::DoAutomaticDenominating -- No Masternodes detected\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- No Masternodes detected\n"); strAutoDenomResult = _("No Masternodes detected."); return false; } @@ -845,7 +845,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool nBalanceNeedsAnonymized = privateSendClient.nPrivateSendAmount*COIN - nBalanceAnonymized; if (nBalanceNeedsAnonymized < 0) { - LogPrint("privatesend", "CPrivateSendClientSession::DoAutomaticDenominating -- Nothing to do\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- Nothing to do\n"); // nothing to do, just keep it in idle mode return false; } @@ -890,7 +890,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool nBalanceNeedsAnonymized += nAdditionalDenom; } - LogPrint("privatesend", "CPrivateSendClientSession::DoAutomaticDenominating -- current stats:\n" + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::DoAutomaticDenominating -- current stats:\n" " nValueMin: %s\n" " nBalanceAnonymizable: %s\n" " nBalanceAnonymized: %s\n" @@ -1000,11 +1000,11 @@ bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool // If we've used 90% of the Masternode list then drop the oldest first ~30% int nThreshold_high = nMnCountEnabled * 0.9; int nThreshold_low = nThreshold_high * 0.7; - LogPrint("privatesend", "Checking vecMasternodesUsed: size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high); + LogPrint(BCLog::PRIVATESEND, "Checking vecMasternodesUsed: size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high); if ((int)vecMasternodesUsed.size() > nThreshold_high) { vecMasternodesUsed.erase(vecMasternodesUsed.begin(), vecMasternodesUsed.begin() + vecMasternodesUsed.size() - nThreshold_low); - LogPrint("privatesend", " vecMasternodesUsed: new size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high); + LogPrint(BCLog::PRIVATESEND, " vecMasternodesUsed: new size: %d, threshold: %d\n", (int)vecMasternodesUsed.size(), nThreshold_high); } LOCK(cs_deqsessions); @@ -1064,11 +1064,11 @@ CDeterministicMNCPtr CPrivateSendClientManager::GetRandomNotUsedMasternode() continue; } - LogPrint("masternode", "CPrivateSendClientManager::%s -- found, masternode=%s\n", __func__, dmn->collateralOutpoint.ToStringShort()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::%s -- found, masternode=%s\n", __func__, dmn->collateralOutpoint.ToStringShort()); return dmn; } - LogPrint("masternode", "CPrivateSendClientManager::%s -- failed\n", __func__); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::%s -- failed\n", __func__); return nullptr; } @@ -1105,7 +1105,7 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize // in order for dsq to get into vecPrivateSendQueue, so we should be safe to mix already, // no need for additional verification here - LogPrint("privatesend", "CPrivateSendClientSession::JoinExistingQueue -- found valid queue: %s\n", dsq.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::JoinExistingQueue -- found valid queue: %s\n", dsq.ToString()); std::vector > vecPSInOutPairsTmp; CAmount nMinAmount = vecStandardDenoms[vecBits.front()]; @@ -1222,7 +1222,7 @@ bool CPrivateSendClientSession::ProcessPendingDsaRequest(CConnman& connman) if (!pendingDsaRequest) return false; bool fDone = connman.ForNode(pendingDsaRequest.GetAddr(), [&](CNode* pnode) { - LogPrint("privatesend", "-- processing dsa queue for addr=%s\n", pnode->addr.ToString()); + LogPrint(BCLog::PRIVATESEND, "-- processing dsa queue for addr=%s\n", pnode->addr.ToString()); nTimeLastSuccessfulStep = GetTime(); // TODO: this vvvv should be here after new state POOL_STATE_CONNECTING is added and MIN_PRIVATESEND_PEER_PROTO_VERSION is bumped // SetState(POOL_STATE_QUEUE); @@ -1234,7 +1234,7 @@ bool CPrivateSendClientSession::ProcessPendingDsaRequest(CConnman& connman) if (fDone) { pendingDsaRequest = CPendingDsaRequest(); } else if (pendingDsaRequest.IsExpired()) { - LogPrint("privatesend", "CPrivateSendClientSession::%s -- failed to connect to %s\n", __func__, pendingDsaRequest.GetAddr().ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::%s -- failed to connect to %s\n", __func__, pendingDsaRequest.GetAddr().ToString()); SetNull(); } @@ -1275,7 +1275,7 @@ bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman) } vecInputsByRounds.emplace_back(i, vecPSInOutPairsTmp.size()); } else { - LogPrint("privatesend", "CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, error: %s\n", i, strError); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::SubmitDenominate -- Running PrivateSend denominate for %d rounds, error: %s\n", i, strError); } } @@ -1284,9 +1284,9 @@ bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman) return a.second > b.second || (a.second == b.second && a.first < b.first); }); - LogPrint("privatesend", "vecInputsByRounds for denom %d\n", nSessionDenom); + LogPrint(BCLog::PRIVATESEND, "vecInputsByRounds for denom %d\n", nSessionDenom); for (const auto& pair : vecInputsByRounds) { - LogPrint("privatesend", "vecInputsByRounds: rounds: %d, inputs: %d\n", pair.first, pair.second); + LogPrint(BCLog::PRIVATESEND, "vecInputsByRounds: rounds: %d, inputs: %d\n", pair.first, pair.second); } int nRounds = vecInputsByRounds.begin()->first; @@ -1422,7 +1422,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman) std::vector vecTally; if (!pwalletMain->SelectCoinsGroupedByAddresses(vecTally, false, false)) { - LogPrint("privatesend", "CPrivateSendClientSession::MakeCollateralAmounts -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); return false; } @@ -1535,7 +1535,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // This still leaves more than enough room for another data of typical CreateDenominated tx. std::vector vecTally; if (!pwalletMain->SelectCoinsGroupedByAddresses(vecTally, true, true, true, 400)) { - LogPrint("privatesend", "CPrivateSendClientSession::CreateDenominated -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); return false; } @@ -1566,7 +1566,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, CAmount nValueLeft = tallyItem.nAmount; nValueLeft -= CPrivateSend::GetCollateralAmount(); // leave some room for fees - LogPrint("privatesend", "CPrivateSendClientSession::CreateDenominated -- 0 - %s nValueLeft: %f\n", CBitcoinAddress(tallyItem.txdest).ToString(), (float)nValueLeft / COIN); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 0 - %s nValueLeft: %f\n", CBitcoinAddress(tallyItem.txdest).ToString(), (float)nValueLeft / COIN); // ****** Add an output for mixing collaterals ************ / @@ -1591,14 +1591,14 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // check skipped denoms if (privateSendClient.IsDenomSkipped(nDenomValue)) { strAutoDenomResult = strprintf(_("Too many %f denominations, skipping."), (float)nDenomValue / COIN); - LogPrint("privatesend", "CPrivateSendClientSession::CreateDenominated -- %s\n", strAutoDenomResult); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- %s\n", strAutoDenomResult); continue; } // find new denoms to skip if any (ignore the largest one) if (nDenomValue != vecStandardDenoms.front() && pwalletMain->CountInputsWithAmount(nDenomValue) > privateSendClient.nPrivateSendDenoms) { strAutoDenomResult = strprintf(_("Too many %f denominations, removing."), (float)nDenomValue / COIN); - LogPrint("privatesend", "CPrivateSendClientSession::CreateDenominated -- %s\n", strAutoDenomResult); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- %s\n", strAutoDenomResult); privateSendClient.AddSkippedDenom(nDenomValue); continue; } @@ -1625,13 +1625,13 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, nOutputs++; nValueLeft -= nDenomValue; nBalanceToDenominate -= nDenomValue; - LogPrint("privatesend", "CPrivateSendClientSession::CreateDenominated -- 1 - totalOutputs: %d, nOutputsTotal: %d, nOutputs: %d, nValueLeft: %f\n", nOutputsTotal + nOutputs, nOutputsTotal, nOutputs, (float)nValueLeft / COIN); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 1 - totalOutputs: %d, nOutputsTotal: %d, nOutputs: %d, nValueLeft: %f\n", nOutputsTotal + nOutputs, nOutputsTotal, nOutputs, (float)nValueLeft / COIN); } nOutputsTotal += nOutputs; if (nValueLeft == 0 || nBalanceToDenominate <= 0) break; } - LogPrint("privatesend", "CPrivateSendClientSession::CreateDenominated -- 2 - nOutputsTotal: %d, nValueLeft: %f\n", nOutputsTotal, (float)nValueLeft / COIN); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- 2 - nOutputsTotal: %d, nValueLeft: %f\n", nOutputsTotal, (float)nValueLeft / COIN); // No reasons to create mixing collaterals if we can't create denoms to mix if (nOutputsTotal == 0) return false; @@ -1697,7 +1697,7 @@ void CPrivateSendClientSession::SetState(PoolState nStateNew) void CPrivateSendClientManager::UpdatedBlockTip(const CBlockIndex* pindex) { nCachedBlockHeight = pindex->nHeight; - LogPrint("privatesend", "CPrivateSendClientManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::UpdatedBlockTip -- nCachedBlockHeight: %d\n", nCachedBlockHeight); } void CPrivateSendClientManager::DoMaintenance(CConnman& connman) diff --git a/src/privatesend/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp index 8b3771a0d0e2..f41c5c7bf8d8 100644 --- a/src/privatesend/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -30,7 +30,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (strCommand == NetMsgType::DSACCEPT) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint("privatesend", "DSACCEPT -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSACCEPT -- 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", MIN_PRIVATESEND_PEER_PROTO_VERSION))); PushStatus(pfrom, STATUS_REJECTED, ERR_VERSION, connman); return; @@ -46,7 +46,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm CPrivateSendAccept dsa; vRecv >> dsa; - LogPrint("privatesend", "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CPrivateSend::GetDenominationsToString(dsa.nDenom), dsa.txCollateral.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSACCEPT -- nDenom %d (%s) txCollateral %s", dsa.nDenom, CPrivateSend::GetDenominationsToString(dsa.nDenom), dsa.txCollateral.ToString()); auto mnList = deterministicMNManager->GetListAtChainTip(); auto dmn = mnList.GetValidMNByCollateral(activeMasternodeInfo.outpoint); @@ -63,7 +63,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm for (const auto& q : vecPrivateSendQueue) { if (q.masternodeOutpoint == activeMasternodeInfo.outpoint) { // refuse to create another queue this often - LogPrint("privatesend", "DSACCEPT -- last dsq is still in queue, refuse to mix\n"); + LogPrint(BCLog::PRIVATESEND, "DSACCEPT -- last dsq is still in queue, refuse to mix\n"); PushStatus(pfrom, STATUS_REJECTED, ERR_RECENT, connman); return; } @@ -97,7 +97,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (!lockRecv) return; if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint("privatesend", "DSQUEUE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- 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", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -108,12 +108,12 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm // process every dsq only once for (const auto& q : vecPrivateSendQueue) { if (q == dsq) { - // LogPrint("privatesend", "DSQUEUE -- %s seen\n", dsq.ToString()); + // LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- %s seen\n", dsq.ToString()); return; } } - LogPrint("privatesend", "DSQUEUE -- %s new\n", dsq.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- %s new\n", dsq.ToString()); if (dsq.IsExpired()) return; @@ -131,29 +131,29 @@ 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", dmn->pdmnState->addr.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Masternode %s is sending WAY too many dsq messages\n", dmn->pdmnState->addr.ToString()); return; } } 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()); + LogPrint(BCLog::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 (nLastDsq != 0 && nThreshold > mmetaman.GetDsqCount()) { - LogPrint("privatesend", "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->pdmnState->addr.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->pdmnState->addr.ToString()); return; } mmetaman.AllowMixing(dmn->proTxHash); - LogPrint("privatesend", "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- new PrivateSend queue (%s) from masternode %s\n", dsq.ToString(), dmn->pdmnState->addr.ToString()); vecPrivateSendQueue.push_back(dsq); dsq.Relay(connman); } } else if (strCommand == NetMsgType::DSVIN) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint("privatesend", "DSVIN -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSVIN -- 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", MIN_PRIVATESEND_PEER_PROTO_VERSION))); PushStatus(pfrom, STATUS_REJECTED, ERR_VERSION, connman); return; @@ -169,7 +169,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm CPrivateSendEntry entry; vRecv >> entry; - LogPrint("privatesend", "DSVIN -- txCollateral %s", entry.txCollateral->ToString()); + LogPrint(BCLog::PRIVATESEND, "DSVIN -- txCollateral %s", entry.txCollateral->ToString()); if (entry.vecTxDSIn.size() > PRIVATESEND_ENTRY_MAX_SIZE) { LogPrintf("DSVIN -- ERROR: too many inputs! %d/%d\n", entry.vecTxDSIn.size(), PRIVATESEND_ENTRY_MAX_SIZE); @@ -216,7 +216,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm for (const auto& txin : entry.vecTxDSIn) { tx.vin.push_back(txin); - LogPrint("privatesend", "DSVIN -- txin=%s\n", txin.ToString()); + LogPrint(BCLog::PRIVATESEND, "DSVIN -- txin=%s\n", txin.ToString()); Coin coin; auto mempoolTx = mempool.get(txin.prevout.hash); @@ -258,7 +258,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm } else if (strCommand == NetMsgType::DSSIGNFINALTX) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint("privatesend", "DSSIGNFINALTX -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSSIGNFINALTX -- 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", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -266,7 +266,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm std::vector vecTxIn; vRecv >> vecTxIn; - LogPrint("privatesend", "DSSIGNFINALTX -- vecTxIn.size() %s\n", vecTxIn.size()); + LogPrint(BCLog::PRIVATESEND, "DSSIGNFINALTX -- vecTxIn.size() %s\n", vecTxIn.size()); int nTxInIndex = 0; int nTxInsCount = (int)vecTxIn.size(); @@ -274,11 +274,11 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm for (const auto& txin : vecTxIn) { nTxInIndex++; if (!AddScriptSig(txin)) { - LogPrint("privatesend", "DSSIGNFINALTX -- AddScriptSig() failed at %d/%d, session: %d\n", nTxInIndex, nTxInsCount, nSessionID); + LogPrint(BCLog::PRIVATESEND, "DSSIGNFINALTX -- AddScriptSig() failed at %d/%d, session: %d\n", nTxInIndex, nTxInsCount, nSessionID); RelayStatus(STATUS_REJECTED, connman); return; } - LogPrint("privatesend", "DSSIGNFINALTX -- AddScriptSig() %d/%d success\n", nTxInIndex, nTxInsCount); + LogPrint(BCLog::PRIVATESEND, "DSSIGNFINALTX -- AddScriptSig() %d/%d success\n", nTxInIndex, nTxInsCount); } // all is good CheckPool(connman); @@ -302,18 +302,18 @@ void CPrivateSendServer::CheckPool(CConnman& connman) { if (!fMasternodeMode) return; - LogPrint("privatesend", "CPrivateSendServer::CheckPool -- entries count %lu\n", GetEntriesCount()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CheckPool -- entries count %lu\n", GetEntriesCount()); // If entries are full, create finalized transaction if (nState == POOL_STATE_ACCEPTING_ENTRIES && GetEntriesCount() >= nSessionMaxParticipants) { - LogPrint("privatesend", "CPrivateSendServer::CheckPool -- FINALIZE TRANSACTIONS\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CheckPool -- FINALIZE TRANSACTIONS\n"); CreateFinalTransaction(connman); return; } // If we have all of the signatures, try to compile the transaction if (nState == POOL_STATE_SIGNING && IsSignaturesComplete()) { - LogPrint("privatesend", "CPrivateSendServer::CheckPool -- SIGNING\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CheckPool -- SIGNING\n"); CommitFinalTransaction(connman); return; } @@ -321,7 +321,7 @@ void CPrivateSendServer::CheckPool(CConnman& connman) void CPrivateSendServer::CreateFinalTransaction(CConnman& connman) { - LogPrint("privatesend", "CPrivateSendServer::CreateFinalTransaction -- FINALIZE TRANSACTIONS\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CreateFinalTransaction -- FINALIZE TRANSACTIONS\n"); CMutableTransaction txNew; @@ -338,7 +338,7 @@ void CPrivateSendServer::CreateFinalTransaction(CConnman& connman) sort(txNew.vout.begin(), txNew.vout.end(), CompareOutputBIP69()); finalMutableTransaction = txNew; - LogPrint("privatesend", "CPrivateSendServer::CreateFinalTransaction -- finalMutableTransaction=%s", txNew.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CreateFinalTransaction -- finalMutableTransaction=%s", txNew.ToString()); // request signatures from clients SetState(POOL_STATE_SIGNING); @@ -352,7 +352,7 @@ void CPrivateSendServer::CommitFinalTransaction(CConnman& connman) CTransactionRef finalTransaction = MakeTransactionRef(finalMutableTransaction); uint256 hashTx = finalTransaction->GetHash(); - LogPrint("privatesend", "CPrivateSendServer::CommitFinalTransaction -- finalTransaction=%s", finalTransaction->ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CommitFinalTransaction -- finalTransaction=%s", finalTransaction->ToString()); { // See if the transaction is valid @@ -389,7 +389,7 @@ void CPrivateSendServer::CommitFinalTransaction(CConnman& connman) ChargeRandomFees(connman); // Reset - LogPrint("privatesend", "CPrivateSendServer::CommitFinalTransaction -- COMPLETED -- RESETTING\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CommitFinalTransaction -- COMPLETED -- RESETTING\n"); SetNull(); } @@ -519,14 +519,14 @@ void CPrivateSendServer::CheckTimeout(CConnman& connman) // See if we have at least min number of participants, if so - we can still do smth if (nState == POOL_STATE_QUEUE && vecSessionCollaterals.size() >= CPrivateSend::GetMinPoolParticipants()) { - LogPrint("privatesend", "CPrivateSendServer::CheckTimeout -- Queue for %d participants timed out (%ds) -- falling back to %d participants\n", + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CheckTimeout -- Queue for %d participants timed out (%ds) -- falling back to %d participants\n", nSessionMaxParticipants, nTimeout, vecSessionCollaterals.size()); nSessionMaxParticipants = vecSessionCollaterals.size(); return; } if (nState == POOL_STATE_ACCEPTING_ENTRIES && GetEntriesCount() >= CPrivateSend::GetMinPoolParticipants()) { - LogPrint("privatesend", "CPrivateSendServer::CheckTimeout -- Accepting entries for %d participants timed out (%ds) -- falling back to %d participants\n", + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CheckTimeout -- Accepting entries for %d participants timed out (%ds) -- falling back to %d participants\n", nSessionMaxParticipants, nTimeout, GetEntriesCount()); // Punish misbehaving participants ChargeFees(connman); @@ -537,7 +537,7 @@ void CPrivateSendServer::CheckTimeout(CConnman& connman) } // All other cases - LogPrint("privatesend", "CPrivateSendServer::CheckTimeout -- %s timed out (%ds) -- resetting\n", + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CheckTimeout -- %s timed out (%ds) -- resetting\n", (nState == POOL_STATE_SIGNING) ? "Signing" : "Session", nTimeout); ChargeFees(connman); SetNull(); @@ -556,7 +556,7 @@ void CPrivateSendServer::CheckForCompleteQueue(CConnman& connman) SetState(POOL_STATE_ACCEPTING_ENTRIES); CPrivateSendQueue dsq(nSessionDenom, activeMasternodeInfo.outpoint, GetAdjustedTime(), true); - LogPrint("privatesend", "CPrivateSendServer::CheckForCompleteQueue -- queue is ready, signing and relaying (%s)\n", dsq.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CheckForCompleteQueue -- queue is ready, signing and relaying (%s)\n", dsq.ToString()); dsq.Sign(); dsq.Relay(connman); } @@ -590,17 +590,17 @@ bool CPrivateSendServer::IsInputScriptSigValid(const CTxIn& txin) if (nTxInIndex >= 0) { //might have to do this one input at a time? txNew.vin[nTxInIndex].scriptSig = txin.scriptSig; - LogPrint("privatesend", "CPrivateSendServer::IsInputScriptSigValid -- verifying scriptSig %s\n", ScriptToAsmStr(txin.scriptSig).substr(0, 24)); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::IsInputScriptSigValid -- verifying scriptSig %s\n", ScriptToAsmStr(txin.scriptSig).substr(0, 24)); if (!VerifyScript(txNew.vin[nTxInIndex].scriptSig, sigPubKey, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, MutableTransactionSignatureChecker(&txNew, nTxInIndex))) { - LogPrint("privatesend", "CPrivateSendServer::IsInputScriptSigValid -- VerifyScript() failed on input %d\n", nTxInIndex); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::IsInputScriptSigValid -- VerifyScript() failed on input %d\n", nTxInIndex); return false; } } else { - LogPrint("privatesend", "CPrivateSendServer::IsInputScriptSigValid -- Failed to find matching input in pool, %s\n", txin.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::IsInputScriptSigValid -- Failed to find matching input in pool, %s\n", txin.ToString()); return false; } - LogPrint("privatesend", "CPrivateSendServer::IsInputScriptSigValid -- Successfully validated input and scriptSig\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::IsInputScriptSigValid -- Successfully validated input and scriptSig\n"); return true; } @@ -613,30 +613,30 @@ bool CPrivateSendServer::AddEntry(const CPrivateSendEntry& entryNew, PoolMessage for (const auto& txin : entryNew.vecTxDSIn) { if (txin.prevout.IsNull()) { - LogPrint("privatesend", "CPrivateSendServer::AddEntry -- input not valid!\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddEntry -- input not valid!\n"); nMessageIDRet = ERR_INVALID_INPUT; return false; } } if (!CPrivateSend::IsCollateralValid(*entryNew.txCollateral)) { - LogPrint("privatesend", "CPrivateSendServer::AddEntry -- collateral not valid!\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddEntry -- collateral not valid!\n"); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; } if (GetEntriesCount() >= nSessionMaxParticipants) { - LogPrint("privatesend", "CPrivateSendServer::AddEntry -- entries is full!\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddEntry -- entries is full!\n"); nMessageIDRet = ERR_ENTRIES_FULL; return false; } for (const auto& txin : entryNew.vecTxDSIn) { - LogPrint("privatesend", "looking for txin -- %s\n", txin.ToString()); + LogPrint(BCLog::PRIVATESEND, "looking for txin -- %s\n", txin.ToString()); for (const auto& entry : vecEntries) { for (const auto& txdsin : entry.vecTxDSIn) { if (txdsin.prevout == txin.prevout) { - LogPrint("privatesend", "CPrivateSendServer::AddEntry -- found in txin\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddEntry -- found in txin\n"); nMessageIDRet = ERR_ALREADY_HAVE; return false; } @@ -646,7 +646,7 @@ bool CPrivateSendServer::AddEntry(const CPrivateSendEntry& entryNew, PoolMessage vecEntries.push_back(entryNew); - LogPrint("privatesend", "CPrivateSendServer::AddEntry -- adding entry %d of %d required\n", GetEntriesCount(), nSessionMaxParticipants); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddEntry -- adding entry %d of %d required\n", GetEntriesCount(), nSessionMaxParticipants); nMessageIDRet = MSG_ENTRIES_ADDED; return true; @@ -654,33 +654,33 @@ bool CPrivateSendServer::AddEntry(const CPrivateSendEntry& entryNew, PoolMessage bool CPrivateSendServer::AddScriptSig(const CTxIn& txinNew) { - LogPrint("privatesend", "CPrivateSendServer::AddScriptSig -- scriptSig=%s\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24)); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddScriptSig -- scriptSig=%s\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24)); for (const auto& entry : vecEntries) { for (const auto& txdsin : entry.vecTxDSIn) { if (txdsin.scriptSig == txinNew.scriptSig) { - LogPrint("privatesend", "CPrivateSendServer::AddScriptSig -- already exists\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddScriptSig -- already exists\n"); return false; } } } if (!IsInputScriptSigValid(txinNew)) { - LogPrint("privatesend", "CPrivateSendServer::AddScriptSig -- Invalid scriptSig\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddScriptSig -- Invalid scriptSig\n"); return false; } - LogPrint("privatesend", "CPrivateSendServer::AddScriptSig -- scriptSig=%s new\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24)); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddScriptSig -- scriptSig=%s new\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24)); for (auto& txin : finalMutableTransaction.vin) { if (txin.prevout == txinNew.prevout && txin.nSequence == txinNew.nSequence) { txin.scriptSig = txinNew.scriptSig; - LogPrint("privatesend", "CPrivateSendServer::AddScriptSig -- adding to finalMutableTransaction, scriptSig=%s\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24)); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddScriptSig -- adding to finalMutableTransaction, scriptSig=%s\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24)); } } for (int i = 0; i < GetEntriesCount(); i++) { if (vecEntries[i].AddScriptSig(txinNew)) { - LogPrint("privatesend", "CPrivateSendServer::AddScriptSig -- adding to entries, scriptSig=%s\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24)); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::AddScriptSig -- adding to entries, scriptSig=%s\n", ScriptToAsmStr(txinNew.scriptSig).substr(0, 24)); return true; } } @@ -719,14 +719,14 @@ bool CPrivateSendServer::IsAcceptableDSA(const CPrivateSendAccept& dsa, PoolMess // is denom even smth legit? std::vector vecBits; if (!CPrivateSend::GetDenominationsBits(dsa.nDenom, vecBits)) { - LogPrint("privatesend", "CPrivateSendServer::%s -- denom not valid!\n", __func__); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::%s -- denom not valid!\n", __func__); nMessageIDRet = ERR_DENOM; return false; } // check collateral if (!fUnitTest && !CPrivateSend::IsCollateralValid(dsa.txCollateral)) { - LogPrint("privatesend", "CPrivateSendServer::%s -- collateral not valid!\n", __func__); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::%s -- collateral not valid!\n", __func__); nMessageIDRet = ERR_INVALID_COLLATERAL; return false; } @@ -760,7 +760,7 @@ bool CPrivateSendServer::CreateNewSession(const CPrivateSendAccept& dsa, PoolMes if (!fUnitTest) { //broadcast that I'm accepting entries, only if it's the first entry through CPrivateSendQueue dsq(nSessionDenom, activeMasternodeInfo.outpoint, GetAdjustedTime(), false); - LogPrint("privatesend", "CPrivateSendServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::CreateNewSession -- signing and relaying new queue: %s\n", dsq.ToString()); dsq.Sign(); dsq.Relay(connman); vecPrivateSendQueue.push_back(dsq); @@ -813,7 +813,7 @@ bool CPrivateSendServer::IsSessionReady() void CPrivateSendServer::RelayFinalTransaction(const CTransaction& txFinal, CConnman& connman) { - LogPrint("privatesend", "CPrivateSendServer::%s -- nSessionID: %d nSessionDenom: %d (%s)\n", + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::%s -- nSessionID: %d nSessionDenom: %d (%s)\n", __func__, nSessionID, nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom)); // final mixing tx with empty signatures should be relayed to mixing participants only @@ -876,7 +876,7 @@ void CPrivateSendServer::RelayStatus(PoolStatusUpdate nStatusUpdate, CConnman& c void CPrivateSendServer::RelayCompletedTransaction(PoolMessage nMessageID, CConnman& connman) { - LogPrint("privatesend", "CPrivateSendServer::%s -- nSessionID: %d nSessionDenom: %d (%s)\n", + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::%s -- nSessionID: %d nSessionDenom: %d (%s)\n", __func__, nSessionID, nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom)); // final mixing tx with empty signatures should be relayed to mixing participants only @@ -899,7 +899,7 @@ void CPrivateSendServer::SetState(PoolState nStateNew) if (!fMasternodeMode) return; if (nStateNew == POOL_STATE_ERROR || nStateNew == POOL_STATE_SUCCESS) { - LogPrint("privatesend", "CPrivateSendServer::SetState -- Can't set state to ERROR or SUCCESS as a Masternode. \n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendServer::SetState -- Can't set state to ERROR or SUCCESS as a Masternode. \n"); return; } diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 654e6e4cc917..856f91678026 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -150,7 +150,7 @@ void CPrivateSendBaseManager::CheckQueue() std::vector::iterator it = vecPrivateSendQueue.begin(); while (it != vecPrivateSendQueue.end()) { if ((*it).IsExpired()) { - LogPrint("privatesend", "CPrivateSendBaseManager::%s -- Removing expired queue (%s)\n", __func__, (*it).ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendBaseManager::%s -- Removing expired queue (%s)\n", __func__, (*it).ToString()); it = vecPrivateSendQueue.erase(it); } else ++it; @@ -243,31 +243,31 @@ bool CPrivateSend::IsCollateralValid(const CTransaction& txCollateral) auto mempoolTx = mempool.get(txin.prevout.hash); if (mempoolTx != nullptr) { if (mempool.isSpent(txin.prevout) || !llmq::quorumInstantSendManager->IsLocked(txin.prevout.hash)) { - LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- spent or non-locked mempool input! txin=%s\n", txin.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::IsCollateralValid -- spent or non-locked mempool input! txin=%s\n", txin.ToString()); return false; } nValueIn += mempoolTx->vout[txin.prevout.n].nValue; } else if (GetUTXOCoin(txin.prevout, coin)) { nValueIn += coin.out.nValue; } else { - LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- Unknown inputs in collateral transaction, txCollateral=%s", txCollateral.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::IsCollateralValid -- Unknown inputs in collateral transaction, txCollateral=%s", txCollateral.ToString()); return false; } } //collateral transactions are required to pay out a small fee to the miners if (nValueIn - nValueOut < GetCollateralAmount()) { - LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- did not include enough fees in transaction: fees: %d, txCollateral=%s", nValueOut - nValueIn, txCollateral.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::IsCollateralValid -- did not include enough fees in transaction: fees: %d, txCollateral=%s", nValueOut - nValueIn, txCollateral.ToString()); return false; } - LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- %s", txCollateral.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::IsCollateralValid -- %s", txCollateral.ToString()); { LOCK(cs_main); CValidationState validationState; if (!AcceptToMemoryPool(mempool, validationState, MakeTransactionRef(txCollateral), false, NULL, false, maxTxFee, true)) { - LogPrint("privatesend", "CPrivateSend::IsCollateralValid -- didn't pass AcceptToMemoryPool()\n"); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::IsCollateralValid -- didn't pass AcceptToMemoryPool()\n"); return false; } } @@ -474,7 +474,7 @@ void CPrivateSend::CheckDSTXes(int nHeight) ++it; } } - LogPrint("privatesend", "CPrivateSend::CheckDSTXes -- mapDSTX.size()=%llu\n", mapDSTX.size()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::CheckDSTXes -- mapDSTX.size()=%llu\n", mapDSTX.size()); } void CPrivateSend::UpdatedBlockTip(const CBlockIndex* pindex) @@ -495,5 +495,5 @@ void CPrivateSend::SyncTransaction(const CTransaction& tx, const CBlockIndex* pi // When tx is 0-confirmed or conflicted, posInBlock is SYNC_TRANSACTION_NOT_IN_BLOCK and nConfirmedHeight should be set to -1 mapDSTX[txHash].SetConfirmedHeight(posInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK ? -1 : pindex->nHeight); - LogPrint("privatesend", "CPrivateSend::SyncTransaction -- txid=%s\n", txHash.ToString()); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::SyncTransaction -- txid=%s\n", txHash.ToString()); } diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index d6b555c85331..9ab17d030661 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -765,7 +765,7 @@ void CoinControlDialog::updateView() COutPoint outpoint = COutPoint(out.tx->tx->GetHash(), out.i); int nRounds = pwalletMain->GetRealOutpointPrivateSendRounds(outpoint); - if (nRounds >= 0 || fDebug) itemOutput->setText(COLUMN_PRIVATESEND_ROUNDS, QString::number(nRounds)); + if (nRounds >= 0 || LogAcceptCategory(BCLog::PRIVATESEND)) itemOutput->setText(COLUMN_PRIVATESEND_ROUNDS, QString::number(nRounds)); else itemOutput->setText(COLUMN_PRIVATESEND_ROUNDS, tr("n/a")); itemOutput->setData(COLUMN_PRIVATESEND_ROUNDS, Qt::UserRole, QVariant((qlonglong)nRounds)); diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp index d2ef82847107..94a22ac21131 100644 --- a/src/qt/dash.cpp +++ b/src/qt/dash.cpp @@ -156,15 +156,21 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans #if QT_VERSION < 0x050000 void DebugMessageHandler(QtMsgType type, const char *msg) { - const char *category = (type == QtDebugMsg) ? "qt" : NULL; - LogPrint(category, "GUI: %s\n", msg); + if (type == QtDebugMsg) { + LogPrint(BCLog::QT, "GUI: %s\n", msg); + } else { + LogPrintf("GUI: %s\n", msg); + } } #else void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg) { Q_UNUSED(context); - const char *category = (type == QtDebugMsg) ? "qt" : NULL; - LogPrint(category, "GUI: %s\n", msg.toStdString()); + if (type == QtDebugMsg) { + LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString()); + } else { + LogPrintf("GUI: %s\n", msg.toStdString()); + } } #endif diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 1a8f7e0e55cc..f4bcbac87f3a 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -571,7 +571,7 @@ void OverviewPage::privateSendStatus() QString s = tr("Last PrivateSend message:\n") + strStatus; if(s != ui->labelPrivateSendLastMessage->text()) - LogPrint("privatesend", "OverviewPage::privateSendStatus -- Last PrivateSend message: %s\n", strStatus.toStdString()); + LogPrint(BCLog::PRIVATESEND, "OverviewPage::privateSendStatus -- Last PrivateSend message: %s\n", strStatus.toStdString()); ui->labelPrivateSendLastMessage->setText(s); @@ -626,7 +626,7 @@ void OverviewPage::togglePrivateSend(){ QMessageBox::warning(this, tr("PrivateSend"), tr("Wallet is locked and user declined to unlock. Disabling PrivateSend."), QMessageBox::Ok, QMessageBox::Ok); - LogPrint("privatesend", "OverviewPage::togglePrivateSend -- Wallet is locked and user declined to unlock. Disabling PrivateSend.\n"); + LogPrint(BCLog::PRIVATESEND, "OverviewPage::togglePrivateSend -- Wallet is locked and user declined to unlock. Disabling PrivateSend.\n"); return; } } diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 5e823d666292..16525b104b9b 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -307,7 +307,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // // Debug view // - if (fDebug) + if (logCategories != BCLog::NONE) { strHTML += "

" + tr("Debug information") + "

"; BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) diff --git a/src/random.cpp b/src/random.cpp index 8db22a5980cb..5d1a4c564d4b 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -91,7 +91,7 @@ static void RandAddSeedPerfmon() if (ret == ERROR_SUCCESS) { RAND_add(vData.data(), nSize, nSize / 100.0); memory_cleanse(vData.data(), nSize); - LogPrint("rand", "%s: %lu bytes\n", __func__, nSize); + LogPrint(BCLog::RANDOM, "%s: %lu bytes\n", __func__, nSize); } else { static bool warned = false; // Warn only once if (!warned) { diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 897a282936c6..68ac4d76ed2f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1114,7 +1114,7 @@ UniValue pruneblockchain(const JSONRPCRequest& request) else if (height > chainHeight) throw JSONRPCError(RPC_INVALID_PARAMETER, "Blockchain is shorter than the attempted prune height."); else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) { - LogPrint("rpc", "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks."); + LogPrint(BCLog::RPC, "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks."); height = chainHeight - MIN_BLOCKS_TO_KEEP; } diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 7a573de36d82..f9c23b60d9a6 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -220,7 +220,7 @@ UniValue gobject_prepare(const JSONRPCRequest& request) throw JSONRPCError(RPC_INTERNAL_ERROR, "CommitTransaction failed! Reason given: " + state.GetRejectReason()); } - LogPrint("gobject", "gobject_prepare -- GetDataAsPlainString = %s, hash = %s, txid = %s\n", + LogPrint(BCLog::GOBJECT, "gobject_prepare -- GetDataAsPlainString = %s, hash = %s, txid = %s\n", govobj.GetDataAsPlainString(), govobj.GetHash().ToString(), wtx.GetHash().ToString()); return wtx.GetHash().ToString(); @@ -253,7 +253,7 @@ UniValue gobject_submit(const JSONRPCRequest& request) auto mnList = deterministicMNManager->GetListAtChainTip(); bool fMnFound = mnList.HasValidMNByCollateral(activeMasternodeInfo.outpoint); - LogPrint("gobject", "gobject_submit -- pubKeyOperator = %s, outpoint = %s, params.size() = %lld, fMnFound = %d\n", + LogPrint(BCLog::GOBJECT, "gobject_submit -- pubKeyOperator = %s, outpoint = %s, params.size() = %lld, fMnFound = %d\n", (activeMasternodeInfo.blsPubKeyOperator ? activeMasternodeInfo.blsPubKeyOperator->ToString() : "N/A"), activeMasternodeInfo.outpoint.ToStringShort(), request.params.size(), fMnFound); @@ -281,7 +281,7 @@ UniValue gobject_submit(const JSONRPCRequest& request) CGovernanceObject govobj(hashParent, nRevision, nTime, txidFee, strDataHex); - LogPrint("gobject", "gobject_submit -- GetDataAsPlainString = %s, hash = %s, txid = %s\n", + LogPrint(BCLog::GOBJECT, "gobject_submit -- GetDataAsPlainString = %s, hash = %s, txid = %s\n", govobj.GetDataAsPlainString(), govobj.GetHash().ToString(), request.params[5].get_str()); if (govobj.GetObjectType() == GOVERNANCE_OBJECT_PROPOSAL) { diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index a543556b9ccb..b226f39bd156 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -134,7 +134,7 @@ UniValue debug(const JSONRPCRequest& request) " addrman, alert, bench, cmpctblock, coindb, db, http, leveldb, libevent, lock, mempool,\n" " mempoolrej, net, proxy, prune, qt, rand, reindex, rpc, selectcoins, tor, zmq, dash\n" " (or specifically: chainlocks, gobject, instantsend, keepass, llmq, llmq-dkg, llmq-sigs,\n" - " masternode, mnpayments, mnsync, privatesend, spork).\n" + " mnpayments, mnsync, privatesend, spork).\n" " Can also use \"1\" to turn all categories on at once and \"0\" to turn them off.\n" " Note: If specified category doesn't match any of the above, no error is thrown.\n" "\nResult:\n" @@ -145,17 +145,21 @@ UniValue debug(const JSONRPCRequest& request) ); std::string strMode = request.params[0].get_str(); + logCategories = BCLog::NONE; - std::vector newMultiArgs; - boost::split(newMultiArgs, strMode, boost::is_any_of("+")); - ForceSetMultiArgs("-debug", newMultiArgs); - ForceSetArg("-debug", newMultiArgs[newMultiArgs.size() - 1]); + std::vector categories; + boost::split(categories, strMode, boost::is_any_of("+")); - fDebug = GetArg("-debug", "") != "0"; - - ResetLogAcceptCategoryCache(); + if (std::find(categories.begin(), categories.end(), std::string("0")) == categories.end()) { + for (const auto& cat : categories) { + uint64_t flag; + if (GetLogCategory(&flag, &cat)) { + logCategories |= flag; + } + } + } - return "Debug mode: " + (fDebug ? strMode : "off"); + return "Debug mode: " + ListActiveLogCategories(); } UniValue mnsync(const JSONRPCRequest& request) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index ab53d4f98b33..d437fb929dd9 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -363,7 +363,7 @@ bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd) bool StartRPC() { - LogPrint("rpc", "Starting RPC\n"); + LogPrint(BCLog::RPC, "Starting RPC\n"); fRPCRunning = true; g_rpcSignals.Started(); return true; @@ -371,14 +371,14 @@ bool StartRPC() void InterruptRPC() { - LogPrint("rpc", "Interrupting RPC\n"); + LogPrint(BCLog::RPC, "Interrupting RPC\n"); // Interrupt e.g. running longpolls fRPCRunning = false; } void StopRPC() { - LogPrint("rpc", "Stopping RPC\n"); + LogPrint(BCLog::RPC, "Stopping RPC\n"); deadlineTimers.clear(); DeleteAuthCookie(); g_rpcSignals.Stopped(); @@ -427,8 +427,9 @@ void JSONRPCRequest::parse(const UniValue& valRequest) if (!valMethod.isStr()) throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string"); strMethod = valMethod.get_str(); - if (strMethod != "getblocktemplate") - LogPrint("rpc", "ThreadRPCServer method=%s\n", SanitizeString(strMethod)); + if (strMethod != "getblocktemplate") { + LogPrint(BCLog::RPC, "ThreadRPCServer method=%s\n", SanitizeString(strMethod)); + } // Parse params UniValue valParams = find_value(request, "params"); @@ -599,7 +600,7 @@ void RPCRunLater(const std::string& name, boost::function func, int6 if (!timerInterface) throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC"); deadlineTimers.erase(name); - LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name()); + LogPrint(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name()); deadlineTimers.emplace(name, std::unique_ptr(timerInterface->NewTimer(func, nSeconds*1000))); } diff --git a/src/spork.cpp b/src/spork.cpp index 011031023e8c..776b12b8826a 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -154,7 +154,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, const std::string& strCommand, CD if (mapSporksActive.count(spork.nSporkID)) { if (mapSporksActive[spork.nSporkID].count(keyIDSigner)) { if (mapSporksActive[spork.nSporkID][keyIDSigner].nTimeSigned >= spork.nTimeSigned) { - LogPrint("spork", "%s seen\n", strLogMsg); + LogPrint(BCLog::SPORK, "%s seen\n", strLogMsg); return; } else { LogPrintf("%s updated\n", strLogMsg); @@ -204,7 +204,7 @@ void CSporkManager::ExecuteSpork(int nSporkID, int nValue) static int64_t nTimeExecuted = 0; // i.e. it was never executed before if(GetTime() - nTimeExecuted < nTimeout) { - LogPrint("spork", "CSporkManager::ExecuteSpork -- ERROR: Trying to reconsider blocks, too soon - %d/%d\n", GetTime() - nTimeExecuted, nTimeout); + LogPrint(BCLog::SPORK, "CSporkManager::ExecuteSpork -- ERROR: Trying to reconsider blocks, too soon - %d/%d\n", GetTime() - nTimeExecuted, nTimeout); return; } @@ -257,7 +257,7 @@ bool CSporkManager::IsSporkActive(int nSporkID) return mapSporkDefaults[nSporkID] < GetAdjustedTime(); } - LogPrint("spork", "CSporkManager::IsSporkActive -- Unknown Spork ID %d\n", nSporkID); + LogPrint(BCLog::SPORK, "CSporkManager::IsSporkActive -- Unknown Spork ID %d\n", nSporkID); return false; } @@ -274,7 +274,7 @@ int64_t CSporkManager::GetSporkValue(int nSporkID) return mapSporkDefaults[nSporkID]; } - LogPrint("spork", "CSporkManager::GetSporkValue -- Unknown Spork ID %d\n", nSporkID); + LogPrint(BCLog::SPORK, "CSporkManager::GetSporkValue -- Unknown Spork ID %d\n", nSporkID); return -1; } @@ -292,7 +292,7 @@ int CSporkManager::GetSporkIDByName(const std::string& strName) if (strName == "SPORK_19_CHAINLOCKS_ENABLED") return SPORK_19_CHAINLOCKS_ENABLED; if (strName == "SPORK_20_INSTANTSEND_LLMQ_BASED") return SPORK_20_INSTANTSEND_LLMQ_BASED; - LogPrint("spork", "CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName); + LogPrint(BCLog::SPORK, "CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName); return -1; } @@ -311,7 +311,7 @@ std::string CSporkManager::GetSporkNameByID(int nSporkID) case SPORK_19_CHAINLOCKS_ENABLED: return "SPORK_19_CHAINLOCKS_ENABLED"; case SPORK_20_INSTANTSEND_LLMQ_BASED: return "SPORK_20_INSTANTSEND_LLMQ_BASED"; default: - LogPrint("spork", "CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID); + LogPrint(BCLog::SPORK, "CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID); return "Unknown"; } } diff --git a/src/timedata.cpp b/src/timedata.cpp index a70fe23771a1..dbec1fa76be6 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -58,7 +58,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) // Add data static CMedianFilter vTimeOffsets(BITCOIN_TIMEDATA_MAX_SAMPLES, 0); vTimeOffsets.input(nOffsetSample); - LogPrint("net","added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); + LogPrint(BCLog::NET,"added time data, samples %d, offset %+d (%+d minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); // There is a known issue here (see issue #4521): // @@ -108,11 +108,14 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) } } } - - BOOST_FOREACH(int64_t n, vSorted) - LogPrint("net", "%+d ", n); - LogPrint("net", "| "); - - LogPrint("net", "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60); + + if (LogAcceptCategory(BCLog::NET)) { + BOOST_FOREACH(int64_t n, vSorted) { + LogPrint(BCLog::NET, "%+d ", n); + } + LogPrint(BCLog::NET, "| "); + + LogPrint(BCLog::NET, "nTimeOffset = %+d (%+d minutes)\n", nTimeOffset, nTimeOffset/60); + } } } diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 453cb1f170c1..2ab6a558ee35 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -163,7 +163,7 @@ void TorControlConnection::readcb(struct bufferevent *bev, void *ctx) self->reply_handlers.front()(*self, self->message); self->reply_handlers.pop_front(); } else { - LogPrint("tor", "tor: Received unexpected sync reply %i\n", self->message.code); + LogPrint(BCLog::TOR, "tor: Received unexpected sync reply %i\n", self->message.code); } } self->message.Clear(); @@ -182,13 +182,14 @@ void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ct { TorControlConnection *self = (TorControlConnection*)ctx; if (what & BEV_EVENT_CONNECTED) { - LogPrint("tor", "tor: Successfully connected!\n"); + LogPrint(BCLog::TOR, "tor: Successfully connected!\n"); self->connected(*self); } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) { - if (what & BEV_EVENT_ERROR) - LogPrint("tor", "tor: Error connecting to Tor control socket\n"); - else - LogPrint("tor", "tor: End of stream\n"); + if (what & BEV_EVENT_ERROR) { + LogPrint(BCLog::TOR, "tor: Error connecting to Tor control socket\n"); + } else { + LogPrint(BCLog::TOR, "tor: End of stream\n"); + } self->Disconnect(); self->disconnected(*self); } @@ -410,7 +411,7 @@ TorController::TorController(struct event_base* _base, const std::string& _targe // Read service private key if cached std::pair pkf = ReadBinaryFile(GetPrivateKeyFile()); if (pkf.first) { - LogPrint("tor", "tor: Reading cached private key from %s\n", GetPrivateKeyFile()); + LogPrint(BCLog::TOR, "tor: Reading cached private key from %s\n", GetPrivateKeyFile()); private_key = pkf.second; } } @@ -429,7 +430,7 @@ TorController::~TorController() void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { - LogPrint("tor", "tor: ADD_ONION successful\n"); + LogPrint(BCLog::TOR, "tor: ADD_ONION successful\n"); BOOST_FOREACH(const std::string &s, reply.lines) { std::map m = ParseTorReplyMapping(s); std::map::iterator i; @@ -441,7 +442,7 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe service = LookupNumeric(std::string(service_id+".onion").c_str(), GetListenPort()); LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString()); if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { - LogPrint("tor", "tor: Cached service private key to %s\n", GetPrivateKeyFile()); + LogPrint(BCLog::TOR, "tor: Cached service private key to %s\n", GetPrivateKeyFile()); } else { LogPrintf("tor: Error writing service private key to %s\n", GetPrivateKeyFile()); } @@ -457,7 +458,7 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { - LogPrint("tor", "tor: Authentication successful\n"); + LogPrint(BCLog::TOR, "tor: Authentication successful\n"); // Now that we know Tor is running setup the proxy for onion addresses // if -onion isn't set to something else. @@ -511,13 +512,13 @@ static std::vector ComputeResponse(const std::string &key, const std::v void TorController::authchallenge_cb(TorControlConnection& _conn, const TorControlReply& reply) { if (reply.code == 250) { - LogPrint("tor", "tor: SAFECOOKIE authentication challenge successful\n"); + LogPrint(BCLog::TOR, "tor: SAFECOOKIE authentication challenge successful\n"); std::pair l = SplitTorReplyLine(reply.lines[0]); if (l.first == "AUTHCHALLENGE") { std::map m = ParseTorReplyMapping(l.second); std::vector serverHash = ParseHex(m["SERVERHASH"]); std::vector serverNonce = ParseHex(m["SERVERNONCE"]); - LogPrint("tor", "tor: AUTHCHALLENGE ServerHash %s ServerNonce %s\n", HexStr(serverHash), HexStr(serverNonce)); + LogPrint(BCLog::TOR, "tor: AUTHCHALLENGE ServerHash %s ServerNonce %s\n", HexStr(serverHash), HexStr(serverNonce)); if (serverNonce.size() != 32) { LogPrintf("tor: ServerNonce is not 32 bytes, as required by spec\n"); return; @@ -562,12 +563,12 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro std::map m = ParseTorReplyMapping(l.second); std::map::iterator i; if ((i = m.find("Tor")) != m.end()) { - LogPrint("tor", "tor: Connected to Tor version %s\n", i->second); + LogPrint(BCLog::TOR, "tor: Connected to Tor version %s\n", i->second); } } } BOOST_FOREACH(const std::string &s, methods) { - LogPrint("tor", "tor: Supported authentication method: %s\n", s); + LogPrint(BCLog::TOR, "tor: Supported authentication method: %s\n", s); } // Prefer NULL, otherwise SAFECOOKIE. If a password is provided, use HASHEDPASSWORD /* Authentication: @@ -577,18 +578,18 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro std::string torpassword = GetArg("-torpassword", ""); if (!torpassword.empty()) { if (methods.count("HASHEDPASSWORD")) { - LogPrint("tor", "tor: Using HASHEDPASSWORD authentication\n"); + LogPrint(BCLog::TOR, "tor: Using HASHEDPASSWORD authentication\n"); boost::replace_all(torpassword, "\"", "\\\""); _conn.Command("AUTHENTICATE \"" + torpassword + "\"", boost::bind(&TorController::auth_cb, this, _1, _2)); } else { LogPrintf("tor: Password provided with -torpassword, but HASHEDPASSWORD authentication is not available\n"); } } else if (methods.count("NULL")) { - LogPrint("tor", "tor: Using NULL authentication\n"); + LogPrint(BCLog::TOR, "tor: Using NULL authentication\n"); _conn.Command("AUTHENTICATE", boost::bind(&TorController::auth_cb, this, _1, _2)); } else if (methods.count("SAFECOOKIE")) { // Cookie: hexdump -e '32/1 "%02x""\n"' ~/.tor/control_auth_cookie - LogPrint("tor", "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile); + LogPrint(BCLog::TOR, "tor: Using SAFECOOKIE authentication, reading cookie authentication from %s\n", cookiefile); std::pair status_cookie = ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE); if (status_cookie.first && status_cookie.second.size() == TOR_COOKIE_SIZE) { // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second), boost::bind(&TorController::auth_cb, this, _1, _2)); @@ -630,7 +631,7 @@ void TorController::disconnected_cb(TorControlConnection& _conn) if (!reconnect) return; - LogPrint("tor", "tor: Not connected to Tor control port %s, trying to reconnect\n", target); + LogPrint(BCLog::TOR, "tor: Not connected to Tor control port %s, trying to reconnect\n", target); // Single-shot timer for reconnect. Use exponential backoff. struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0)); diff --git a/src/txdb.cpp b/src/txdb.cpp index ac38cc8a3457..17596e414d04 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -95,7 +95,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { batch.Write(DB_BEST_BLOCK, hashBlock); bool ret = db.WriteBatch(batch); - LogPrint("coindb", "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count); + LogPrint(BCLog::COINDB, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count); return ret; } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index de9c9bdb3af8..49c071e87280 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1022,7 +1022,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const if (GetRand(std::numeric_limits::max()) >= nCheckFrequency) return; - LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); + LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); uint64_t checkTotal = 0; uint64_t innerUsage = 0; @@ -1603,8 +1603,9 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector* pvNoSpends } } - if (maxFeeRateRemoved > CFeeRate(0)) - LogPrint("mempool", "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString()); + if (maxFeeRateRemoved > CFeeRate(0)) { + LogPrint(BCLog::MEMPOOL, "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString()); + } } bool CTxMemPool::TransactionWithinChainLimit(const uint256& txid, size_t chainLimit) const { diff --git a/src/util.cpp b/src/util.cpp index 580bf7248b3c..5934b141c987 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -129,7 +129,6 @@ CCriticalSection cs_args; std::unordered_map mapArgs; static std::unordered_map > _mapMultiArgs; const std::unordered_map >& mapMultiArgs = _mapMultiArgs; -bool fDebug = false; bool fPrintToConsole = false; bool fPrintToDebugLog = true; @@ -140,6 +139,9 @@ bool fLogIPs = DEFAULT_LOGIPS; std::atomic fReopenDebugLog(false); CTranslationInterface translationInterface; +/** Log categories bitfield. Leveldb/libevent need special handling if their flags are changed at runtime. */ +std::atomic logCategories(0); + /** Init OpenSSL library multithreading support */ static std::unique_ptr ppmutexOpenSSL; void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS @@ -213,7 +215,6 @@ static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT; static FILE* fileout = NULL; static boost::mutex* mutexDebugLog = NULL; static std::list* vMsgsBeforeOpenLog; -static std::atomic logAcceptCategoryCacheCounter(0); static int FileWriteStr(const std::string &str, FILE *fp) { @@ -249,71 +250,120 @@ void OpenDebugLog() vMsgsBeforeOpenLog = NULL; } -bool LogAcceptCategory(const char* category) +struct CLogCategoryDesc { - if (category != NULL) - { - // Give each thread quick access to -debug settings. - // This helps prevent issues debugging global destructors, - // where mapMultiArgs might be deleted before another - // global destructor calls LogPrint() - static boost::thread_specific_ptr > ptrCategory; - static boost::thread_specific_ptr cacheCounter; - - if (!fDebug) { - if (ptrCategory.get() != NULL) { - LogPrintf("debug turned off: thread %s\n", GetThreadName()); - ptrCategory.release(); - } - return false; - } + uint64_t flag; + std::string category; +}; - if (ptrCategory.get() == NULL || *cacheCounter != logAcceptCategoryCacheCounter.load()) - { - cacheCounter.reset(new int(logAcceptCategoryCacheCounter.load())); - - LOCK(cs_args); - if (mapMultiArgs.count("-debug")) { - std::string strThreadName = GetThreadName(); - LogPrintf("debug turned on:\n"); - for (int i = 0; i < (int)mapMultiArgs.at("-debug").size(); ++i) - LogPrintf(" thread %s category %s\n", strThreadName, mapMultiArgs.at("-debug")[i]); - const std::vector& categories = mapMultiArgs.at("-debug"); - ptrCategory.reset(new std::set(categories.begin(), categories.end())); - // thread_specific_ptr automatically deletes the set when the thread ends. - // "dash" is a composite category enabling all Dash-related debug output - if(ptrCategory->count(std::string("dash"))) { - ptrCategory->insert(std::string("chainlocks")); - ptrCategory->insert(std::string("gobject")); - ptrCategory->insert(std::string("instantsend")); - ptrCategory->insert(std::string("keepass")); - ptrCategory->insert(std::string("llmq")); - ptrCategory->insert(std::string("llmq-dkg")); - ptrCategory->insert(std::string("llmq-sigs")); - ptrCategory->insert(std::string("masternode")); - ptrCategory->insert(std::string("mnpayments")); - ptrCategory->insert(std::string("mnsync")); - ptrCategory->insert(std::string("spork")); - ptrCategory->insert(std::string("privatesend")); - } - } else { - ptrCategory.reset(new std::set()); +const CLogCategoryDesc LogCategories[] = +{ + {BCLog::NONE, "0"}, + {BCLog::NET, "net"}, + {BCLog::TOR, "tor"}, + {BCLog::MEMPOOL, "mempool"}, + {BCLog::HTTP, "http"}, + {BCLog::BENCHMARK, "bench"}, + {BCLog::ZMQ, "zmq"}, + {BCLog::DB, "db"}, + {BCLog::RPC, "rpc"}, + {BCLog::ESTIMATEFEE, "estimatefee"}, + {BCLog::ADDRMAN, "addrman"}, + {BCLog::SELECTCOINS, "selectcoins"}, + {BCLog::REINDEX, "reindex"}, + {BCLog::CMPCTBLOCK, "cmpctblock"}, + {BCLog::RANDOM, "rand"}, + {BCLog::PRUNE, "prune"}, + {BCLog::PROXY, "proxy"}, + {BCLog::MEMPOOLREJ, "mempoolrej"}, + {BCLog::LIBEVENT, "libevent"}, + {BCLog::COINDB, "coindb"}, + {BCLog::QT, "qt"}, + {BCLog::LEVELDB, "leveldb"}, + {BCLog::ALL, "1"}, + {BCLog::ALL, "all"}, + + //Start Dash + {BCLog::CHAINLOCKS, "chainlocks"}, + {BCLog::GOBJECT, "gobject"}, + {BCLog::INSTANTSEND, "instantsend"}, + {BCLog::KEEPASS, "keepass"}, + {BCLog::LLMQ, "llmq"}, + {BCLog::LLMQ_DKG, "llmq-dkg"}, + {BCLog::LLMQ_SIGS, "llmq-sigs"}, + {BCLog::MNPAYMENTS, "mnpayments"}, + {BCLog::MNSYNC, "mnsync"}, + {BCLog::PRIVATESEND, "privatesend"}, + {BCLog::SPORK, "spork"}, + {BCLog::ALERT, "alert"}, + //End Dash + +}; + +bool GetLogCategory(uint64_t *f, const std::string *str) +{ + if (f && str) { + if (*str == "") { + *f = BCLog::ALL; + return true; + } + if (*str == "dash") { + *f = BCLog::CHAINLOCKS + | BCLog::GOBJECT + | BCLog::INSTANTSEND + | BCLog::KEEPASS + | BCLog::LLMQ + | BCLog::LLMQ_DKG + | BCLog::LLMQ_SIGS + | BCLog::MNPAYMENTS + | BCLog::MNSYNC + | BCLog::PRIVATESEND + | BCLog::SPORK; + return true; + } + for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) { + if (LogCategories[i].category == *str) { + *f = LogCategories[i].flag; + return true; } } - const std::set& setCategories = *ptrCategory; + } + return false; +} - // if not debugging everything and not debugging specific category, LogPrint does nothing. - if (setCategories.count(std::string("")) == 0 && - setCategories.count(std::string("1")) == 0 && - setCategories.count(std::string(category)) == 0) - return false; +std::string ListLogCategories() +{ + std::string ret; + int outcount = 0; + for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) { + // Omit the special cases. + if (LogCategories[i].flag != BCLog::NONE && LogCategories[i].flag != BCLog::ALL) { + if (outcount != 0) ret += ", "; + ret += LogCategories[i].category; + outcount++; + } } - return true; + return ret; } -void ResetLogAcceptCategoryCache() +std::string ListActiveLogCategories() { - logAcceptCategoryCacheCounter++; + if (logCategories == BCLog::NONE) + return "0"; + if (logCategories == BCLog::ALL) + return "1"; + + std::string ret; + int outcount = 0; + for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) { + // Omit the special cases. + if (LogCategories[i].flag != BCLog::NONE && LogCategories[i].flag != BCLog::ALL && LogAcceptCategory(LogCategories[i].flag)) { + if (outcount != 0) ret += ", "; + ret += LogCategories[i].category; + outcount++; + } + } + return ret; } /** diff --git a/src/util.h b/src/util.h index 3dfaa67155c6..0af05ebe35d4 100644 --- a/src/util.h +++ b/src/util.h @@ -63,7 +63,6 @@ class CTranslationInterface }; extern const std::unordered_map >& mapMultiArgs; -extern bool fDebug; extern bool fPrintToConsole; extern bool fPrintToDebugLog; @@ -77,6 +76,8 @@ extern CTranslationInterface translationInterface; extern const char * const BITCOIN_CONF_FILENAME; extern const char * const BITCOIN_PID_FILENAME; +extern std::atomic logCategories; + /** * Translation function: Call Translate signal on UI interface, which returns a boost::optional result. * If no translation slot is registered, nothing is returned, and simply return the input. @@ -90,10 +91,63 @@ inline std::string _(const char* psz) void SetupEnvironment(); bool SetupNetworking(); -/** Return true if log accepts specified category */ -bool LogAcceptCategory(const char* category); -/** Reset internal log category caching (call this when debug categories have changed) */ -void ResetLogAcceptCategoryCache(); +namespace BCLog { + enum LogFlags : uint64_t { + NONE = 0, + NET = (1 << 0), + TOR = (1 << 1), + MEMPOOL = (1 << 2), + HTTP = (1 << 3), + BENCHMARK = (1 << 4), + ZMQ = (1 << 5), + DB = (1 << 6), + RPC = (1 << 7), + ESTIMATEFEE = (1 << 8), + ADDRMAN = (1 << 9), + SELECTCOINS = (1 << 10), + REINDEX = (1 << 11), + CMPCTBLOCK = (1 << 12), + RANDOM = (1 << 13), + PRUNE = (1 << 14), + PROXY = (1 << 15), + MEMPOOLREJ = (1 << 16), + LIBEVENT = (1 << 17), + COINDB = (1 << 18), + QT = (1 << 19), + LEVELDB = (1 << 20), + + //Start Dash + CHAINLOCKS = ((uint64_t)1 << 32), + GOBJECT = ((uint64_t)1 << 33), + INSTANTSEND = ((uint64_t)1 << 34), + KEEPASS = ((uint64_t)1 << 35), + LLMQ = ((uint64_t)1 << 36), + LLMQ_DKG = ((uint64_t)1 << 37), + LLMQ_SIGS = ((uint64_t)1 << 38), + MNPAYMENTS = ((uint64_t)1 << 39), + MNSYNC = ((uint64_t)1 << 40), + PRIVATESEND = ((uint64_t)1 << 41), + SPORK = ((uint64_t)1 << 42), + ALERT = ((uint64_t)1 << 43), + //End Dash + + ALL = ~(uint64_t)0, + }; +} +static inline bool LogAcceptCategory(uint64_t category) +{ + return (logCategories.load(std::memory_order_relaxed) & category) != 0; +} + +/** Returns a string with the supported log categories */ +std::string ListLogCategories(); + +/** Returns a string with the list of active log categories */ +std::string ListActiveLogCategories(); + +/** Return true if str parses as a log category and set the flags in f */ +bool GetLogCategory(uint64_t *f, const std::string *str); + /** Send a string to the log output */ int LogPrintStr(const std::string &str); diff --git a/src/validation.cpp b/src/validation.cpp index 313a078d178c..bd5fea3ffcd1 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -607,8 +607,9 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) { int expired = pool.Expire(GetTime() - age); - if (expired != 0) - LogPrint("mempool", "Expired %i transactions from the memory pool\n", expired); + if (expired != 0) { + LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired); + } std::vector vNoSpendsRemaining; pool.TrimToSize(limit, &vNoSpendsRemaining); @@ -920,7 +921,7 @@ bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const std::vector coins_to_uncache; bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, fDryRun); if (!res || fDryRun) { - if(!res) LogPrint("mempool", "%s: %s %s (%s)\n", __func__, tx->GetHash().ToString(), state.GetRejectReason(), state.GetDebugMessage()); + if(!res) LogPrint(BCLog::MEMPOOL, "%s: %s %s (%s)\n", __func__, tx->GetHash().ToString(), state.GetRejectReason(), state.GetDebugMessage()); BOOST_FOREACH(const COutPoint& hashTx, coins_to_uncache) pcoinsTip->Uncache(hashTx); } @@ -1950,7 +1951,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd } int64_t nTime1 = GetTimeMicros(); nTimeCheck += nTime1 - nTimeStart; - LogPrint("bench", " - Sanity checks: %.2fms [%.2fs]\n", 0.001 * (nTime1 - nTimeStart), nTimeCheck * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Sanity checks: %.2fms [%.2fs]\n", 0.001 * (nTime1 - nTimeStart), nTimeCheck * 0.000001); // Do not allow blocks that contain transactions which 'overwrite' older transactions, // unless those are already completely spent. @@ -2028,7 +2029,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd } int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; - LogPrint("bench", " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Fork checks: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeForks * 0.000001); CBlockUndo blockundo; @@ -2182,12 +2183,12 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); } int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2; - LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), 0.001 * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime3 - nTime2), 0.001 * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * 0.000001); if (!control.Wait()) return state.DoS(100, error("%s: CheckQueue failed", __func__), REJECT_INVALID, "block-validation-failed"); int64_t nTime4 = GetTimeMicros(); nTimeVerify += nTime4 - nTime2; - LogPrint("bench", " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime4 - nTime2), nInputs <= 1 ? 0 : 0.001 * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Verify %u txins: %.2fms (%.3fms/txin) [%.2fs]\n", nInputs - 1, 0.001 * (nTime4 - nTime2), nInputs <= 1 ? 0 : 0.001 * (nTime4 - nTime2) / (nInputs-1), nTimeVerify * 0.000001); // DASH @@ -2238,7 +2239,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd } int64_t nTime5_1 = GetTimeMicros(); nTimeISFilter += nTime5_1 - nTime4; - LogPrint("bench", " - IS filter: %.2fms [%.2fs]\n", 0.001 * (nTime5_1 - nTime4), nTimeISFilter * 0.000001); + LogPrint(BCLog::BENCHMARK, " - IS filter: %.2fms [%.2fs]\n", 0.001 * (nTime5_1 - nTime4), nTimeISFilter * 0.000001); // DASH : MODIFIED TO CHECK MASTERNODE PAYMENTS AND SUPERBLOCKS @@ -2247,14 +2248,14 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd std::string strError = ""; int64_t nTime5_2 = GetTimeMicros(); nTimeSubsidy += nTime5_2 - nTime5_1; - LogPrint("bench", " - GetBlockSubsidy: %.2fms [%.2fs]\n", 0.001 * (nTime5_2 - nTime5_1), nTimeSubsidy * 0.000001); + LogPrint(BCLog::BENCHMARK, " - GetBlockSubsidy: %.2fms [%.2fs]\n", 0.001 * (nTime5_2 - nTime5_1), nTimeSubsidy * 0.000001); if (!IsBlockValueValid(block, pindex->nHeight, blockReward, strError)) { return state.DoS(0, error("ConnectBlock(DASH): %s", strError), REJECT_INVALID, "bad-cb-amount"); } int64_t nTime5_3 = GetTimeMicros(); nTimeValueValid += nTime5_3 - nTime5_2; - LogPrint("bench", " - IsBlockValueValid: %.2fms [%.2fs]\n", 0.001 * (nTime5_3 - nTime5_2), nTimeValueValid * 0.000001); + LogPrint(BCLog::BENCHMARK, " - IsBlockValueValid: %.2fms [%.2fs]\n", 0.001 * (nTime5_3 - nTime5_2), nTimeValueValid * 0.000001); if (!IsBlockPayeeValid(*block.vtx[0], pindex->nHeight, blockReward)) { mapRejectedBlocks.insert(std::make_pair(block.GetHash(), GetTime())); @@ -2263,7 +2264,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd } int64_t nTime5_4 = GetTimeMicros(); nTimePayeeValid += nTime5_4 - nTime5_3; - LogPrint("bench", " - IsBlockPayeeValid: %.2fms [%.2fs]\n", 0.001 * (nTime5_4 - nTime5_3), nTimePayeeValid * 0.000001); + LogPrint(BCLog::BENCHMARK, " - IsBlockPayeeValid: %.2fms [%.2fs]\n", 0.001 * (nTime5_4 - nTime5_3), nTimePayeeValid * 0.000001); if (!ProcessSpecialTxsInBlock(block, pindex, state, fJustCheck, fScriptChecks)) { return error("ConnectBlock(DASH): ProcessSpecialTxsInBlock for block %s failed with %s", @@ -2271,10 +2272,10 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd } int64_t nTime5_5 = GetTimeMicros(); nTimeProcessSpecial += nTime5_5 - nTime5_4; - LogPrint("bench", " - ProcessSpecialTxsInBlock: %.2fms [%.2fs]\n", 0.001 * (nTime5_5 - nTime5_4), nTimeProcessSpecial * 0.000001); + LogPrint(BCLog::BENCHMARK, " - ProcessSpecialTxsInBlock: %.2fms [%.2fs]\n", 0.001 * (nTime5_5 - nTime5_4), nTimeProcessSpecial * 0.000001); int64_t nTime5 = GetTimeMicros(); nTimeDashSpecific += nTime5 - nTime4; - LogPrint("bench", " - Dash specific: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeDashSpecific * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Dash specific: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeDashSpecific * 0.000001); // END DASH @@ -2326,7 +2327,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd view.SetBestBlock(pindex->GetBlockHash()); int64_t nTime6 = GetTimeMicros(); nTimeIndex += nTime6 - nTime5; - LogPrint("bench", " - Index writing: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeIndex * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Index writing: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeIndex * 0.000001); // Watch for changes to the previous coinbase transaction. static uint256 hashPrevBestCoinBase; @@ -2336,7 +2337,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd evoDb->WriteBestBlock(pindex->GetBlockHash()); int64_t nTime7 = GetTimeMicros(); nTimeCallbacks += nTime7 - nTime6; - LogPrint("bench", " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime7 - nTime6), nTimeCallbacks * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Callbacks: %.2fms [%.2fs]\n", 0.001 * (nTime7 - nTime6), nTimeCallbacks * 0.000001); return true; } @@ -2548,7 +2549,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara assert(flushed); dbTx->Commit(); } - LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); + LogPrint(BCLog::BENCHMARK, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); // Write the chain state to disk, if necessary. if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) return false; @@ -2619,7 +2620,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, // Apply the block atomically to the chain state. int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1; int64_t nTime3; - LogPrint("bench", " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * 0.001, nTimeReadFromDisk * 0.000001); { auto dbTx = evoDb->BeginTransaction(); @@ -2632,26 +2633,26 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, return error("ConnectTip(): ConnectBlock %s failed with %s", pindexNew->GetBlockHash().ToString(), FormatStateMessage(state)); } nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2; - LogPrint("bench", " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Connect total: %.2fms [%.2fs]\n", (nTime3 - nTime2) * 0.001, nTimeConnectTotal * 0.000001); bool flushed = view.Flush(); assert(flushed); dbTx->Commit(); } int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3; - LogPrint("bench", " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001); // Write the chain state to disk, if necessary. if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) return false; int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4; - LogPrint("bench", " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); // Remove conflicting transactions from the mempool.; mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); // Update chainActive & related variables. UpdateTip(pindexNew, chainparams); int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; - LogPrint("bench", " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); - LogPrint("bench", "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); + LogPrint(BCLog::BENCHMARK, " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); + LogPrint(BCLog::BENCHMARK, "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); return true; } @@ -3808,7 +3809,7 @@ void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight } } - LogPrint("prune", "Prune: target=%dMiB actual=%dMiB diff=%dMiB max_prune_height=%d removed %d blk/rev pairs\n", + LogPrint(BCLog::PRUNE, "Prune: target=%dMiB actual=%dMiB diff=%dMiB max_prune_height=%d removed %d blk/rev pairs\n", nPruneTarget/1024/1024, nCurrentUsage/1024/1024, ((int64_t)nPruneTarget - (int64_t)nCurrentUsage)/1024/1024, nLastBlockWeCanPrune, count); @@ -4270,7 +4271,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB // detect out of order blocks, and store them for later uint256 hash = block.GetHash(); if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex.find(block.hashPrevBlock) == mapBlockIndex.end()) { - LogPrint("reindex", "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(), + LogPrint(BCLog::REINDEX, "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(), block.hashPrevBlock.ToString()); if (dbp) mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp)); @@ -4286,7 +4287,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB if (state.IsError()) break; } else if (hash != chainparams.GetConsensus().hashGenesisBlock && mapBlockIndex[hash]->nHeight % 1000 == 0) { - LogPrint("reindex", "Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight); + LogPrint(BCLog::REINDEX, "Block Import: already had block %s at height %d\n", hash.ToString(), mapBlockIndex[hash]->nHeight); } // Activate the genesis block so normal node progress can continue @@ -4311,7 +4312,7 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB std::shared_ptr pblockrecursive = std::make_shared(); if (ReadBlockFromDisk(*pblockrecursive, it->second, chainparams.GetConsensus())) { - LogPrint("reindex", "%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(), + LogPrint(BCLog::REINDEX, "%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(), head.ToString()); LOCK(cs_main); CValidationState dummy; diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 199c8402f67c..5d0d50b6de5c 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -118,7 +118,7 @@ void CDBEnv::MakeMock() boost::this_thread::interruption_point(); - LogPrint("db", "CDBEnv::MakeMock\n"); + LogPrint(BCLog::DB, "CDBEnv::MakeMock\n"); dbenv->set_cachesize(1, 0, 1); dbenv->set_lg_bsize(10485760 * 4); @@ -559,7 +559,7 @@ void CDBEnv::Flush(bool fShutdown) { int64_t nStart = GetTimeMillis(); // Flush log data to the actual data file on all files that are not in use - LogPrint("db", "CDBEnv::Flush: Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started"); + LogPrint(BCLog::DB, "CDBEnv::Flush: Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started"); if (!fDbEnvInit) return; { @@ -568,21 +568,21 @@ void CDBEnv::Flush(bool fShutdown) while (mi != mapFileUseCount.end()) { std::string strFile = (*mi).first; int nRefCount = (*mi).second; - LogPrint("db", "CDBEnv::Flush: Flushing %s (refcount = %d)...\n", strFile, nRefCount); + LogPrint(BCLog::DB, "CDBEnv::Flush: Flushing %s (refcount = %d)...\n", strFile, nRefCount); if (nRefCount == 0) { // Move log data to the dat file CloseDb(strFile); - LogPrint("db", "CDBEnv::Flush: %s checkpoint\n", strFile); + LogPrint(BCLog::DB, "CDBEnv::Flush: %s checkpoint\n", strFile); dbenv->txn_checkpoint(0, 0, 0); - LogPrint("db", "CDBEnv::Flush: %s detach\n", strFile); + LogPrint(BCLog::DB, "CDBEnv::Flush: %s detach\n", strFile); if (!fMockDb) dbenv->lsn_reset(strFile.c_str(), 0); - LogPrint("db", "CDBEnv::Flush: %s closed\n", strFile); + LogPrint(BCLog::DB, "CDBEnv::Flush: %s closed\n", strFile); mapFileUseCount.erase(mi++); } else mi++; } - LogPrint("db", "CDBEnv::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart); + LogPrint(BCLog::DB, "CDBEnv::Flush: Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart); if (fShutdown) { char** listp; if (mapFileUseCount.empty()) { @@ -616,7 +616,7 @@ bool CDB::PeriodicFlush(std::string strFile) std::map::iterator mi = bitdb.mapFileUseCount.find(strFile); if (mi != bitdb.mapFileUseCount.end()) { - LogPrint("db", "Flushing %s\n", strFile); + LogPrint(BCLog::DB, "Flushing %s\n", strFile); int64_t nStart = GetTimeMillis(); // Flush wallet file so it's self contained @@ -624,7 +624,7 @@ bool CDB::PeriodicFlush(std::string strFile) bitdb.CheckpointLSN(strFile); bitdb.mapFileUseCount.erase(mi++); - LogPrint("db", "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart); + LogPrint(BCLog::DB, "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart); ret = true; } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 360b1d722689..7bc9ddd2f661 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1903,7 +1903,7 @@ UniValue gettransaction(const JSONRPCRequest& request) " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" " 'send' category of transactions.\n" " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable). Only available for the \n" - " 'send' category of transactions.\n" + " 'send' category of transactions.\n" " }\n" " ,...\n" " ],\n" @@ -2473,7 +2473,7 @@ UniValue setprivatesendrounds(const JSONRPCRequest& request) "setprivatesendrounds rounds\n" "\nSet the number of rounds for PrivateSend mixing.\n" "\nArguments:\n" - "1. rounds (numeric, required) The default number of rounds is " + std::to_string(DEFAULT_PRIVATESEND_ROUNDS) + + "1. rounds (numeric, required) The default number of rounds is " + std::to_string(DEFAULT_PRIVATESEND_ROUNDS) + " Cannot be more than " + std::to_string(MAX_PRIVATESEND_ROUNDS) + " nor less than " + std::to_string(MIN_PRIVATESEND_ROUNDS) + "\nExamples:\n" + HelpExampleCli("setprivatesendrounds", "4") diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 75f0774f0307..8e9d90fe7b83 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1383,7 +1383,7 @@ int CWallet::GetRealOutpointPrivateSendRounds(const COutPoint& outpoint, int nRo std::map::const_iterator mdwi = mDenomWtxes.find(hash); if (mdwi == mDenomWtxes.end()) { // not known yet, let's add it - LogPrint("privatesend", "GetRealOutpointPrivateSendRounds INSERTING %s\n", hash.ToString()); + LogPrint(BCLog::PRIVATESEND, "GetRealOutpointPrivateSendRounds INSERTING %s\n", hash.ToString()); mDenomWtxes[hash] = CMutableTransaction(*wtx); } else if(mDenomWtxes[hash].vout[nout].nRounds != -10) { // found and it's not an initial value, just return it @@ -1394,20 +1394,20 @@ int CWallet::GetRealOutpointPrivateSendRounds(const COutPoint& outpoint, int nRo // bounds check if (nout >= wtx->tx->vout.size()) { // should never actually hit this - LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, -4); + LogPrint(BCLog::PRIVATESEND, "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, -4); return -4; } if (CPrivateSend::IsCollateralAmount(wtx->tx->vout[nout].nValue)) { mDenomWtxes[hash].vout[nout].nRounds = -3; - LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds); + LogPrint(BCLog::PRIVATESEND, "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds); return mDenomWtxes[hash].vout[nout].nRounds; } //make sure the final output is non-denominate if (!CPrivateSend::IsDenominatedAmount(wtx->tx->vout[nout].nValue)) { //NOT DENOM mDenomWtxes[hash].vout[nout].nRounds = -2; - LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds); + LogPrint(BCLog::PRIVATESEND, "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds); return mDenomWtxes[hash].vout[nout].nRounds; } @@ -1419,7 +1419,7 @@ int CWallet::GetRealOutpointPrivateSendRounds(const COutPoint& outpoint, int nRo // this one is denominated but there is another non-denominated output found in the same tx if (!fAllDenoms) { mDenomWtxes[hash].vout[nout].nRounds = 0; - LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds); + LogPrint(BCLog::PRIVATESEND, "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds); return mDenomWtxes[hash].vout[nout].nRounds; } @@ -1439,7 +1439,7 @@ int CWallet::GetRealOutpointPrivateSendRounds(const COutPoint& outpoint, int nRo mDenomWtxes[hash].vout[nout].nRounds = fDenomFound ? (nShortest >= MAX_PRIVATESEND_ROUNDS - 1 ? MAX_PRIVATESEND_ROUNDS : nShortest + 1) // good, we a +1 to the shortest one but only MAX_PRIVATESEND_ROUNDS rounds max allowed : 0; // too bad, we are the fist one in that chain - LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds); + LogPrint(BCLog::PRIVATESEND, "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds); return mDenomWtxes[hash].vout[nout].nRounds; } @@ -2678,7 +2678,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin // try to find nondenom first to prevent unneeded spending of mixed coins for (unsigned int tryDenom = tryDenomStart; tryDenom < 2; tryDenom++) { - LogPrint("selectcoins", "tryDenom: %d\n", tryDenom); + LogPrint(BCLog::SELECTCOINS, "tryDenom: %d\n", tryDenom); vValue.clear(); nTotalLower = 0; BOOST_FOREACH(const COutput &output, vCoins) @@ -2688,7 +2688,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin const CWalletTx *pcoin = output.tx; -// if (fDebug) LogPrint("selectcoins", "value %s confirms %d\n", FormatMoney(pcoin->vout[output.i].nValue), output.nDepth); + // if (logCategories != BCLog::NONE) LogPrint(BCLog::SELECTCOINS, "value %s confirms %d\n", FormatMoney(pcoin->vout[output.i].nValue), output.nDepth); if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs)) continue; @@ -2787,7 +2787,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin s += FormatMoney(vValue[i].first) + " "; } } - LogPrint("selectcoins", "%s - total %s\n", s, FormatMoney(nBest)); + LogPrint(BCLog::SELECTCOINS, "%s - total %s\n", s, FormatMoney(nBest)); } // There is no change in PS, so we know the fee beforehand, @@ -2983,7 +2983,7 @@ bool CWallet::SelectPSInOutPairsByDenominations(int nDenom, CAmount nValueMin, C vecPSInOutPairsRet.emplace_back(CTxDSIn(txin, scriptPubKey), CTxOut(nValue, scriptPubKey, nRounds)); setRecentTxIds.emplace(txHash); nDenomResult |= 1 << nBit; - LogPrint("privatesend", "CWallet::%s -- hash: %s, nValue: %d.%08d, nRounds: %d\n", + LogPrint(BCLog::PRIVATESEND, "CWallet::%s -- hash: %s, nValue: %d.%08d, nRounds: %d\n", __func__, txHash.ToString(), nValue / COIN, nValue % COIN, nRounds); } } @@ -3003,12 +3003,12 @@ bool CWallet::SelectCoinsGroupedByAddresses(std::vector& vecTa if(nMaxOupointsPerAddress != -1 && fAnonymizable && fSkipUnconfirmed) { if(fSkipDenominated && fAnonymizableTallyCachedNonDenom) { vecTallyRet = vecAnonymizableTallyCachedNonDenom; - LogPrint("selectcoins", "SelectCoinsGroupedByAddresses - using cache for non-denom inputs %d\n", vecTallyRet.size()); + LogPrint(BCLog::SELECTCOINS, "SelectCoinsGroupedByAddresses - using cache for non-denom inputs %d\n", vecTallyRet.size()); return vecTallyRet.size() > 0; } if(!fSkipDenominated && fAnonymizableTallyCached) { vecTallyRet = vecAnonymizableTallyCached; - LogPrint("selectcoins", "SelectCoinsGroupedByAddresses - using cache for all inputs %d\n", vecTallyRet.size()); + LogPrint(BCLog::SELECTCOINS, "SelectCoinsGroupedByAddresses - using cache for all inputs %d\n", vecTallyRet.size()); return vecTallyRet.size() > 0; } } @@ -3084,11 +3084,11 @@ bool CWallet::SelectCoinsGroupedByAddresses(std::vector& vecTa } // debug - if (LogAcceptCategory("selectcoins")) { + if (LogAcceptCategory(BCLog::SELECTCOINS)) { std::string strMessage = "SelectCoinsGroupedByAddresses - vecTallyRet:\n"; for (const auto& item : vecTallyRet) strMessage += strprintf(" %s %f\n", CBitcoinAddress(item.txdest).ToString().c_str(), float(item.nAmount)/COIN); - LogPrint("selectcoins", "%s", strMessage); + LogPrint(BCLog::SELECTCOINS, "%s", strMessage); } return vecTallyRet.size() > 0; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 645c8b21e641..d13d3d5faa73 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -778,7 +778,7 @@ DBErrors CWalletDB::ZapSelectTx(std::vector& vTxHashIn, std::vectorInitialize(pcontext)) { - LogPrint("zmq", " Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress()); + LogPrint(BCLog::ZMQ, " Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress()); } else { - LogPrint("zmq", " Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress()); + LogPrint(BCLog::ZMQ, " Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress()); break; } } @@ -119,13 +119,13 @@ bool CZMQNotificationInterface::Initialize() // Called during shutdown sequence void CZMQNotificationInterface::Shutdown() { - LogPrint("zmq", "zmq: Shutdown notification interface\n"); + LogPrint(BCLog::ZMQ, "zmq: Shutdown notification interface\n"); if (pcontext) { for (std::list::iterator i=notifiers.begin(); i!=notifiers.end(); ++i) { CZMQAbstractNotifier *notifier = *i; - LogPrint("zmq", " Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress()); + LogPrint(BCLog::ZMQ, " Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress()); notifier->Shutdown(); } zmq_ctx_destroy(pcontext); diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index e831401cfd54..09662d414b3d 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -98,7 +98,7 @@ bool CZMQAbstractPublishNotifier::Initialize(void *pcontext) } else { - LogPrint("zmq", "zmq: Reusing socket for address %s\n", address); + LogPrint(BCLog::ZMQ, "zmq: Reusing socket for address %s\n", address); psocket = i->second->psocket; mapPublishNotifiers.insert(std::make_pair(address, this)); @@ -128,7 +128,7 @@ void CZMQAbstractPublishNotifier::Shutdown() if (count == 1) { - LogPrint("zmq", "Close socket at address %s\n", address); + LogPrint(BCLog::ZMQ, "Close socket at address %s\n", address); int linger = 0; zmq_setsockopt(psocket, ZMQ_LINGER, &linger, sizeof(linger)); zmq_close(psocket); @@ -157,7 +157,7 @@ bool CZMQAbstractPublishNotifier::SendMessage(const char *command, const void* d bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex) { uint256 hash = pindex->GetBlockHash(); - LogPrint("zmq", "zmq: Publish hashblock %s\n", hash.GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish hashblock %s\n", hash.GetHex()); char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; @@ -167,7 +167,7 @@ bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex) bool CZMQPublishHashChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex) { uint256 hash = pindex->GetBlockHash(); - LogPrint("zmq", "zmq: Publish hashchainlock %s\n", hash.GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish hashchainlock %s\n", hash.GetHex()); char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; @@ -177,7 +177,7 @@ bool CZMQPublishHashChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction) { uint256 hash = transaction.GetHash(); - LogPrint("zmq", "zmq: Publish hashtx %s\n", hash.GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish hashtx %s\n", hash.GetHex()); char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; @@ -187,7 +187,7 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t bool CZMQPublishHashTransactionLockNotifier::NotifyTransactionLock(const CTransaction &transaction) { uint256 hash = transaction.GetHash(); - LogPrint("zmq", "zmq: Publish hashtxlock %s\n", hash.GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish hashtxlock %s\n", hash.GetHex()); char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; @@ -197,7 +197,7 @@ bool CZMQPublishHashTransactionLockNotifier::NotifyTransactionLock(const CTransa bool CZMQPublishHashGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote) { uint256 hash = vote.GetHash(); - LogPrint("zmq", "zmq: Publish hashgovernancevote %s\n", hash.GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish hashgovernancevote %s\n", hash.GetHex()); char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; @@ -207,7 +207,7 @@ bool CZMQPublishHashGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernan bool CZMQPublishHashGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &object) { uint256 hash = object.GetHash(); - LogPrint("zmq", "zmq: Publish hashgovernanceobject %s\n", hash.GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish hashgovernanceobject %s\n", hash.GetHex()); char data[32]; for (unsigned int i = 0; i < 32; i++) data[31 - i] = hash.begin()[i]; @@ -217,7 +217,7 @@ bool CZMQPublishHashGovernanceObjectNotifier::NotifyGovernanceObject(const CGove bool CZMQPublishHashInstantSendDoubleSpendNotifier::NotifyInstantSendDoubleSpendAttempt(const CTransaction ¤tTx, const CTransaction &previousTx) { uint256 currentHash = currentTx.GetHash(), previousHash = previousTx.GetHash(); - LogPrint("zmq", "zmq: Publish hashinstantsenddoublespend %s conflicts against %s\n", currentHash.ToString(), previousHash.ToString()); + LogPrint(BCLog::ZMQ, "zmq: Publish hashinstantsenddoublespend %s conflicts against %s\n", currentHash.ToString(), previousHash.ToString()); char dataCurrentHash[32], dataPreviousHash[32]; for (unsigned int i = 0; i < 32; i++) { dataCurrentHash[31 - i] = currentHash.begin()[i]; @@ -230,7 +230,7 @@ bool CZMQPublishHashInstantSendDoubleSpendNotifier::NotifyInstantSendDoubleSpend bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) { - LogPrint("zmq", "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex()); const Consensus::Params& consensusParams = Params().GetConsensus(); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -251,7 +251,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) bool CZMQPublishRawChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex) { - LogPrint("zmq", "zmq: Publish rawchainlock %s\n", pindex->GetBlockHash().GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish rawchainlock %s\n", pindex->GetBlockHash().GetHex()); const Consensus::Params& consensusParams = Params().GetConsensus(); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); @@ -273,7 +273,7 @@ bool CZMQPublishRawChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex) bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction) { uint256 hash = transaction.GetHash(); - LogPrint("zmq", "zmq: Publish rawtx %s\n", hash.GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex()); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << transaction; return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size()); @@ -282,7 +282,7 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr bool CZMQPublishRawTransactionLockNotifier::NotifyTransactionLock(const CTransaction &transaction) { uint256 hash = transaction.GetHash(); - LogPrint("zmq", "zmq: Publish rawtxlock %s\n", hash.GetHex()); + LogPrint(BCLog::ZMQ, "zmq: Publish rawtxlock %s\n", hash.GetHex()); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << transaction; return SendMessage(MSG_RAWTXLOCK, &(*ss.begin()), ss.size()); @@ -291,7 +291,7 @@ bool CZMQPublishRawTransactionLockNotifier::NotifyTransactionLock(const CTransac bool CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote) { uint256 nHash = vote.GetHash(); - LogPrint("gobject", "gobject: Publish rawgovernanceobject: hash = %s, vote = %d\n", nHash.ToString(), vote.ToString()); + LogPrint(BCLog::ZMQ, "gobject: Publish rawgovernanceobject: hash = %s, vote = %d\n", nHash.ToString(), vote.ToString()); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << vote; return SendMessage(MSG_RAWGVOTE, &(*ss.begin()), ss.size()); @@ -300,7 +300,7 @@ bool CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanc bool CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject(const CGovernanceObject &govobj) { uint256 nHash = govobj.GetHash(); - LogPrint("gobject", "gobject: Publish rawgovernanceobject: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType()); + LogPrint(BCLog::ZMQ, "gobject: Publish rawgovernanceobject: hash = %s, type = %d\n", nHash.ToString(), govobj.GetObjectType()); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << govobj; return SendMessage(MSG_RAWGOBJ, &(*ss.begin()), ss.size()); @@ -308,7 +308,7 @@ bool CZMQPublishRawGovernanceObjectNotifier::NotifyGovernanceObject(const CGover bool CZMQPublishRawInstantSendDoubleSpendNotifier::NotifyInstantSendDoubleSpendAttempt(const CTransaction ¤tTx, const CTransaction &previousTx) { - LogPrint("zmq", "zmq: Publish rawinstantsenddoublespend %s conflicts with %s\n", currentTx.GetHash().ToString(), previousTx.GetHash().ToString()); + LogPrint(BCLog::ZMQ, "zmq: Publish rawinstantsenddoublespend %s conflicts with %s\n", currentTx.GetHash().ToString(), previousTx.GetHash().ToString()); CDataStream ssCurrent(SER_NETWORK, PROTOCOL_VERSION), ssPrevious(SER_NETWORK, PROTOCOL_VERSION); ssCurrent << currentTx; ssPrevious << previousTx; From c08e761015958739d4797372b53076d36ca67010 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 23 May 2019 12:13:34 +0300 Subject: [PATCH 088/987] Tighten rules for DSVIN/DSTX (#2897) * Tighten rules for dstx * Tighten rules for dsvin * NULL -> nullptr * Make `ConsumeCollateral()` a private function instead of a lamda and reuse it in `Charge*Fees()` * Make sure inputs and outputs are of the same size Introduces new response ERR_SIZE_MISMATCH, old clients will simply bail out. * Drop now redundant vecTxOut.size() check * Check max inputs size * Fix log category --- src/net_processing.cpp | 4 ++ src/privatesend/privatesend-server.cpp | 58 +++++++++++++++----------- src/privatesend/privatesend-server.h | 2 + src/privatesend/privatesend.cpp | 25 +++++++++++ src/privatesend/privatesend.h | 4 +- 5 files changed, 68 insertions(+), 25 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index db39f78ca9ce..400f4b9342a0 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2156,6 +2156,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } } else if (nInvType == MSG_DSTX) { uint256 hashTx = tx.GetHash(); + if (!dstx.IsValidStructure()) { + LogPrint(BCLog::PRIVATESEND, "DSTX -- Invalid DSTX structure: %s\n", hashTx.ToString()); + return false; + } if(CPrivateSend::GetDSTX(hashTx)) { LogPrint(BCLog::PRIVATESEND, "DSTX -- Already have %s, skipping...\n", hashTx.ToString()); return true; // not an error diff --git a/src/privatesend/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp index f41c5c7bf8d8..5542a79e7467 100644 --- a/src/privatesend/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -171,15 +171,17 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm LogPrint(BCLog::PRIVATESEND, "DSVIN -- txCollateral %s", entry.txCollateral->ToString()); - if (entry.vecTxDSIn.size() > PRIVATESEND_ENTRY_MAX_SIZE) { - LogPrintf("DSVIN -- ERROR: too many inputs! %d/%d\n", entry.vecTxDSIn.size(), PRIVATESEND_ENTRY_MAX_SIZE); - PushStatus(pfrom, STATUS_REJECTED, ERR_MAXIMUM, connman); + if (entry.vecTxDSIn.size() != entry.vecTxOut.size()) { + LogPrintf("DSVIN -- ERROR: inputs vs outputs size mismatch! %d vs %d\n", entry.vecTxDSIn.size(), entry.vecTxOut.size()); + PushStatus(pfrom, STATUS_REJECTED, ERR_SIZE_MISMATCH, connman); + ConsumeCollateral(connman, entry.txCollateral); return; } - if (entry.vecTxOut.size() > PRIVATESEND_ENTRY_MAX_SIZE) { - LogPrintf("DSVIN -- ERROR: too many outputs! %d/%d\n", entry.vecTxOut.size(), PRIVATESEND_ENTRY_MAX_SIZE); + if (entry.vecTxDSIn.size() > PRIVATESEND_ENTRY_MAX_SIZE) { + LogPrintf("DSVIN -- ERROR: too many inputs! %d/%d\n", entry.vecTxDSIn.size(), PRIVATESEND_ENTRY_MAX_SIZE); PushStatus(pfrom, STATUS_REJECTED, ERR_MAXIMUM, connman); + ConsumeCollateral(connman, entry.txCollateral); return; } @@ -204,11 +206,13 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (txout.scriptPubKey.size() != 25) { LogPrintf("DSVIN -- non-standard pubkey detected! scriptPubKey=%s\n", ScriptToAsmStr(txout.scriptPubKey)); PushStatus(pfrom, STATUS_REJECTED, ERR_NON_STANDARD_PUBKEY, connman); + ConsumeCollateral(connman, entry.txCollateral); return; } if (!txout.scriptPubKey.IsPayToPublicKeyHash()) { LogPrintf("DSVIN -- invalid script! scriptPubKey=%s\n", ScriptToAsmStr(txout.scriptPubKey)); PushStatus(pfrom, STATUS_REJECTED, ERR_INVALID_SCRIPT, connman); + ConsumeCollateral(connman, entry.txCollateral); return; } } @@ -226,8 +230,20 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm PushStatus(pfrom, STATUS_REJECTED, ERR_MISSING_TX, connman); return; } + if (!CPrivateSend::IsDenominatedAmount(mempoolTx->vout[txin.prevout.n].nValue)) { + LogPrintf("DSVIN -- non-denominated mempool input! txin=%s\n", txin.ToString()); + PushStatus(pfrom, STATUS_REJECTED, ERR_DENOM, connman); + ConsumeCollateral(connman, entry.txCollateral); + return; + } nValueIn += mempoolTx->vout[txin.prevout.n].nValue; } else if (GetUTXOCoin(txin.prevout, coin)) { + if (!CPrivateSend::IsDenominatedAmount(coin.out.nValue)) { + LogPrintf("DSVIN -- non-denominated input! txin=%s\n", txin.ToString()); + PushStatus(pfrom, STATUS_REJECTED, ERR_DENOM, connman); + ConsumeCollateral(connman, entry.txCollateral); + return; + } nValueIn += coin.out.nValue; } else { LogPrintf("DSVIN -- missing input! txin=%s\n", txin.ToString()); @@ -456,16 +472,7 @@ void CPrivateSendServer::ChargeFees(CConnman& connman) if (nState == POOL_STATE_ACCEPTING_ENTRIES || nState == POOL_STATE_SIGNING) { LogPrintf("CPrivateSendServer::ChargeFees -- found uncooperative node (didn't %s transaction), charging fees: %s", (nState == POOL_STATE_SIGNING) ? "sign" : "send", vecOffendersCollaterals[0]->ToString()); - - LOCK(cs_main); - - CValidationState state; - if (!AcceptToMemoryPool(mempool, state, vecOffendersCollaterals[0], false, NULL, false, maxTxFee)) { - // should never really happen - LogPrintf("CPrivateSendServer::ChargeFees -- ERROR: AcceptToMemoryPool failed!\n"); - } else { - connman.RelayTransaction(*vecOffendersCollaterals[0]); - } + ConsumeCollateral(connman, vecOffendersCollaterals[0]); } } @@ -485,19 +492,22 @@ void CPrivateSendServer::ChargeRandomFees(CConnman& connman) { if (!fMasternodeMode) return; - LOCK(cs_main); - for (const auto& txCollateral : vecSessionCollaterals) { if (GetRandInt(100) > 10) return; LogPrintf("CPrivateSendServer::ChargeRandomFees -- charging random fees, txCollateral=%s", txCollateral->ToString()); + ConsumeCollateral(connman, txCollateral); + } +} - CValidationState state; - if (!AcceptToMemoryPool(mempool, state, txCollateral, false, NULL, false, maxTxFee)) { - // Can happen if this collateral belongs to some misbehaving participant we punished earlier - LogPrintf("CPrivateSendServer::ChargeRandomFees -- ERROR: AcceptToMemoryPool failed!\n"); - } else { - connman.RelayTransaction(*txCollateral); - } +void CPrivateSendServer::ConsumeCollateral(CConnman& connman, const CTransactionRef& txref) +{ + LOCK(cs_main); + CValidationState validationState; + if (!AcceptToMemoryPool(mempool, validationState, txref, false, nullptr)) { + LogPrint(BCLog::PRIVATESEND, "%s -- AcceptToMemoryPool failed\n", __func__); + } else { + connman.RelayTransaction(*txref); + LogPrint(BCLog::PRIVATESEND, "%s -- Collateral was consumed\n", __func__); } } diff --git a/src/privatesend/privatesend-server.h b/src/privatesend/privatesend-server.h index dd7a8fe14018..4d9e02e90b9d 100644 --- a/src/privatesend/privatesend-server.h +++ b/src/privatesend/privatesend-server.h @@ -36,6 +36,8 @@ class CPrivateSendServer : public CPrivateSendBaseSession, public CPrivateSendBa void ChargeFees(CConnman& connman); /// Rarely charge fees to pay miners void ChargeRandomFees(CConnman& connman); + /// Consume collateral in cases when peer misbehaved + void ConsumeCollateral(CConnman& connman, const CTransactionRef& txref); /// Check for process void CheckPool(CConnman& connman); diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 856f91678026..527aad92dc95 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -122,6 +122,29 @@ bool CPrivateSendBroadcastTx::IsExpired(int nHeight) return (nConfirmedHeight != -1) && (nHeight - nConfirmedHeight > 24); } +bool CPrivateSendBroadcastTx::IsValidStructure() +{ + // some trivial checks only + if (tx->vin.size() != tx->vout.size()) { + return false; + } + if (tx->vin.size() < CPrivateSend::GetMinPoolParticipants()) { + return false; + } + if (tx->vin.size() > CPrivateSend::GetMaxPoolParticipants() * PRIVATESEND_ENTRY_MAX_SIZE) { + return false; + } + for (const auto& out : tx->vout) { + if (!CPrivateSend::IsDenominatedAmount(out.nValue)) { + return false; + } + if (!out.scriptPubKey.IsPayToPublicKeyHash()) { + return false; + } + } + return true; +} + void CPrivateSendBaseSession::SetNull() { // Both sides @@ -445,6 +468,8 @@ std::string CPrivateSend::GetMessageByID(PoolMessage nMessageID) return _("Transaction created successfully."); case MSG_ENTRIES_ADDED: return _("Your entries added successfully."); + case ERR_SIZE_MISMATCH: + return _("Inputs vs outputs size mismatch."); default: return _("Unknown response."); } diff --git a/src/privatesend/privatesend.h b/src/privatesend/privatesend.h index 7b315e2bab3c..65f7fb3436cc 100644 --- a/src/privatesend/privatesend.h +++ b/src/privatesend/privatesend.h @@ -52,8 +52,9 @@ enum PoolMessage { MSG_NOERR, MSG_SUCCESS, MSG_ENTRIES_ADDED, + ERR_SIZE_MISMATCH, MSG_POOL_MIN = ERR_ALREADY_HAVE, - MSG_POOL_MAX = MSG_ENTRIES_ADDED + MSG_POOL_MAX = ERR_SIZE_MISMATCH }; // pool states @@ -310,6 +311,7 @@ class CPrivateSendBroadcastTx void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; } bool IsExpired(int nHeight); + bool IsValidStructure(); }; // base class From 428f304506a0cf0c99754e9d150bc683e1de4d49 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 23 May 2019 12:13:58 +0300 Subject: [PATCH 089/987] Implement `rawchainlocksig` and `rawtxlocksig` (#2930) * Pass is-lock into `CInstantSendManager::UpdateWalletTransaction()` * Implement `rawtxlocksig` which pushes tx+islock * Implement `rawchainlocksig` which pushes block+clsig * fix log category --- contrib/zmq/zmq_sub.py | 8 ++++++ contrib/zmq/zmq_sub3.4.py | 8 ++++++ doc/zmq.md | 2 ++ src/dsnotificationinterface.cpp | 2 +- src/dsnotificationinterface.h | 2 +- src/instantsend.cpp | 3 +- src/llmq/quorums_chainlocks.cpp | 2 +- src/llmq/quorums_instantsend.cpp | 20 +++++++------ src/llmq/quorums_instantsend.h | 2 +- src/validationinterface.cpp | 8 +++--- src/validationinterface.h | 13 ++++++--- src/wallet/wallet.cpp | 4 +-- src/wallet/wallet.h | 4 +-- src/zmq/zmqabstractnotifier.cpp | 4 +-- src/zmq/zmqabstractnotifier.h | 9 ++++-- src/zmq/zmqconfig.h | 3 ++ src/zmq/zmqnotificationinterface.cpp | 10 ++++--- src/zmq/zmqnotificationinterface.h | 4 +-- src/zmq/zmqpublishnotifier.cpp | 42 +++++++++++++++++++++++++--- src/zmq/zmqpublishnotifier.h | 20 ++++++++++--- 20 files changed, 126 insertions(+), 44 deletions(-) diff --git a/contrib/zmq/zmq_sub.py b/contrib/zmq/zmq_sub.py index 85b9a730dfbb..2a1dd5277b05 100755 --- a/contrib/zmq/zmq_sub.py +++ b/contrib/zmq/zmq_sub.py @@ -51,8 +51,10 @@ def __init__(self): self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashinstantsenddoublespend") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawblock") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawchainlock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawchainlocksig") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtx") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtxlock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtxlocksig") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawgovernancevote") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawgovernanceobject") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawinstantsenddoublespend") @@ -95,12 +97,18 @@ async def handle(self) : elif topic == b"rawchainlock": print('- RAW CHAINLOCK ('+sequence+') -') print(binascii.hexlify(body[:80]).decode("utf-8")) + elif topic == b"rawchainlocksig": + print('- RAW CHAINLOCK SIG ('+sequence+') -') + print(binascii.hexlify(body[:80]).decode("utf-8")) elif topic == b"rawtx": print('- RAW TX ('+sequence+') -') print(binascii.hexlify(body).decode("utf-8")) elif topic == b"rawtxlock": print('- RAW TX LOCK ('+sequence+') -') print(binascii.hexlify(body).decode("utf-8")) + elif topic == b"rawtxlocksig": + print('- RAW TX LOCK SIG ('+sequence+') -') + print(binascii.hexlify(body).decode("utf-8")) elif topic == b"rawgovernancevote": print('- RAW GOVERNANCE VOTE ('+sequence+') -') print(binascii.hexlify(body).decode("utf-8")) diff --git a/contrib/zmq/zmq_sub3.4.py b/contrib/zmq/zmq_sub3.4.py index b0f7dd18ab4e..446e4103e88b 100755 --- a/contrib/zmq/zmq_sub3.4.py +++ b/contrib/zmq/zmq_sub3.4.py @@ -55,8 +55,10 @@ def __init__(self): self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashinstantsenddoublespend") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawblock") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawchainlock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawchainlocksig") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtx") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtxlock") + self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawtxlocksig") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawgovernancevote") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawgovernanceobject") self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "rawinstantsenddoublespend") @@ -98,12 +100,18 @@ def handle(self) : elif topic == b"rawchainlock": print('- RAW CHAINLOCK ('+sequence+') -') print(binascii.hexlify(body[:80]).decode("utf-8")) + elif topic == b"rawchainlocksig": + print('- RAW CHAINLOCK SIG ('+sequence+') -') + print(binascii.hexlify(body[:80]).decode("utf-8")) elif topic == b"rawtx": print('- RAW TX ('+sequence+') -') print(binascii.hexlify(body).decode("utf-8")) elif topic == b"rawtxlock": print('- RAW TX LOCK ('+sequence+') -') print(binascii.hexlify(body).decode("utf-8")) + elif topic == b"rawtxlocksig": + print('- RAW TX LOCK SIG ('+sequence+') -') + print(binascii.hexlify(body).decode("utf-8")) elif topic == b"rawgovernancevote": print('- RAW GOVERNANCE VOTE ('+sequence+') -') print(binascii.hexlify(body).decode("utf-8")) diff --git a/doc/zmq.md b/doc/zmq.md index 8b90fee8ae4c..b58d94d7f707 100644 --- a/doc/zmq.md +++ b/doc/zmq.md @@ -65,8 +65,10 @@ Currently, the following notifications are supported: -zmqpubhashinstantsenddoublespend=address -zmqpubrawblock=address -zmqpubrawchainlock=address + -zmqpubrawchainlocksig=address -zmqpubrawtx=address -zmqpubrawtxlock=address + -zmqpubrawtxlocksig=address -zmqpubrawgovernancevote=address -zmqpubrawgovernanceobject=address -zmqpubrawinstantsenddoublespend=address diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 9bcf1e3ea16a..684a63df9be5 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -88,7 +88,7 @@ void CDSNotificationInterface::NotifyMasternodeListChanged(bool undo, const CDet governance.UpdateCachesAndClean(); } -void CDSNotificationInterface::NotifyChainLock(const CBlockIndex* pindex) +void CDSNotificationInterface::NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) { llmq::quorumInstantSendManager->NotifyChainLock(pindex); } diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h index 06a8c9ff070a..44873b2b0691 100644 --- a/src/dsnotificationinterface.h +++ b/src/dsnotificationinterface.h @@ -23,7 +23,7 @@ class CDSNotificationInterface : public CValidationInterface void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) override; void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) override; - void NotifyChainLock(const CBlockIndex* pindex) override; + void NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) override; private: CConnman& connman; diff --git a/src/instantsend.cpp b/src/instantsend.cpp index c63614084d6d..5caf89eeca5a 100644 --- a/src/instantsend.cpp +++ b/src/instantsend.cpp @@ -539,7 +539,8 @@ void CInstantSend::UpdateLockedTransaction(const CTxLockCandidate& txLockCandida } #endif - GetMainSignals().NotifyTransactionLock(*txLockCandidate.txLockRequest.tx); + llmq::CInstantSendLock islock; + GetMainSignals().NotifyTransactionLock(*txLockCandidate.txLockRequest.tx, islock); LogPrint(BCLog::INSTANTSEND, "CInstantSend::UpdateLockedTransaction -- done, txid=%s\n", txHash.ToString()); } diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 92e958625ac5..48dded9332d7 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -526,7 +526,7 @@ void CChainLocksHandler::EnforceBestChainLock() } if (pindexNotify) { - GetMainSignals().NotifyChainLock(pindexNotify); + GetMainSignals().NotifyChainLock(pindexNotify, clsig); } } diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index f82fa1194b6f..e6d859c714ef 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -920,31 +920,33 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, const uint256& has RemoveMempoolConflictsForLock(hash, islock); ResolveBlockConflicts(hash, islock); - UpdateWalletTransaction(islock.txid, tx); + UpdateWalletTransaction(tx, islock); } -void CInstantSendManager::UpdateWalletTransaction(const uint256& txid, const CTransactionRef& tx) +void CInstantSendManager::UpdateWalletTransaction(const CTransactionRef& tx, const CInstantSendLock& islock) { + if (tx == nullptr) { + return; + } + #ifdef ENABLE_WALLET if (!pwalletMain) { return; } - if (pwalletMain->UpdatedTransaction(txid)) { + if (pwalletMain->UpdatedTransaction(tx->GetHash())) { // notify an external script once threshold is reached std::string strCmd = GetArg("-instantsendnotify", ""); if (!strCmd.empty()) { - boost::replace_all(strCmd, "%s", txid.GetHex()); + boost::replace_all(strCmd, "%s", tx->GetHash().GetHex()); boost::thread t(runCommand, strCmd); // thread runs free } } #endif - if (tx) { - GetMainSignals().NotifyTransactionLock(*tx); - // bump mempool counter to make sure newly mined txes are picked up by getblocktemplate - mempool.AddTransactionsUpdated(1); - } + GetMainSignals().NotifyTransactionLock(*tx, islock); + // bump mempool counter to make sure newly mined txes are picked up by getblocktemplate + mempool.AddTransactionsUpdated(1); } void CInstantSendManager::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) diff --git a/src/llmq/quorums_instantsend.h b/src/llmq/quorums_instantsend.h index 456ba44bb707..4622ef8b0ac5 100644 --- a/src/llmq/quorums_instantsend.h +++ b/src/llmq/quorums_instantsend.h @@ -139,7 +139,7 @@ class CInstantSendManager : public CRecoveredSigsListener bool PreVerifyInstantSendLock(NodeId nodeId, const CInstantSendLock& islock, bool& retBan); bool ProcessPendingInstantSendLocks(); void ProcessInstantSendLock(NodeId from, const uint256& hash, const CInstantSendLock& islock); - void UpdateWalletTransaction(const uint256& txid, const CTransactionRef& tx); + void UpdateWalletTransaction(const CTransactionRef& tx, const CInstantSendLock& islock); void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock); void AddNonLockedTx(const CTransactionRef& tx); diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index a9f848395508..26fc27a2c06b 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -17,8 +17,8 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.NotifyHeaderTip.connect(boost::bind(&CValidationInterface::NotifyHeaderTip, pwalletIn, _1, _2)); g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3)); - g_signals.NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1)); - g_signals.NotifyChainLock.connect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1)); + g_signals.NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1, _2)); + g_signals.NotifyChainLock.connect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1, _2)); g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); @@ -41,8 +41,8 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); - g_signals.NotifyChainLock.disconnect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1)); - g_signals.NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1)); + g_signals.NotifyChainLock.disconnect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1, _2)); + g_signals.NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1, _2)); g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3)); g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); g_signals.NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); diff --git a/src/validationinterface.h b/src/validationinterface.h index c2abe404a0ce..836d597eaac0 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -24,6 +24,11 @@ class CDeterministicMNList; class CDeterministicMNListDiff; class uint256; +namespace llmq { + class CChainLockSig; + class CInstantSendLock; +} + // These functions dispatch to one or all registered wallets /** Register a wallet to receive updates from core */ @@ -39,8 +44,8 @@ class CValidationInterface { virtual void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) {} virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} virtual void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) {} - virtual void NotifyTransactionLock(const CTransaction &tx) {} - virtual void NotifyChainLock(const CBlockIndex* pindex) {} + virtual void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) {} + virtual void NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) {} virtual void NotifyGovernanceVote(const CGovernanceVote &vote) {} virtual void NotifyGovernanceObject(const CGovernanceObject &object) {} virtual void NotifyInstantSendDoubleSpendAttempt(const CTransaction ¤tTx, const CTransaction &previousTx) {} @@ -77,9 +82,9 @@ struct CMainSignals { * disconnected block.*/ boost::signals2::signal SyncTransaction; /** Notifies listeners of an updated transaction lock without new data. */ - boost::signals2::signal NotifyTransactionLock; + boost::signals2::signal NotifyTransactionLock; /** Notifies listeners of a ChainLock. */ - boost::signals2::signal NotifyChainLock; + boost::signals2::signal NotifyChainLock; /** Notifies listeners of a new governance vote. */ boost::signals2::signal NotifyGovernanceVote; /** Notifies listeners of a new governance object. */ diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8e9d90fe7b83..ea8d78f94c88 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5319,7 +5319,7 @@ bool AutoBackupWallet(CWallet* wallet, const std::string& strWalletFile_, std::s return true; } -void CWallet::NotifyTransactionLock(const CTransaction &tx) +void CWallet::NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) { LOCK(cs_wallet); // Only notify UI if this transaction is in this wallet @@ -5329,7 +5329,7 @@ void CWallet::NotifyTransactionLock(const CTransaction &tx) } } -void CWallet::NotifyChainLock(const CBlockIndex* pindexChainLock) +void CWallet::NotifyChainLock(const CBlockIndex* pindexChainLock, const llmq::CChainLockSig& clsig) { NotifyChainLockReceived(pindexChainLock->nHeight); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 859a42c67fb0..b5543aa8d66c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1172,8 +1172,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool SetCryptedHDChain(const CHDChain& chain, bool memonly); bool GetDecryptedHDChain(CHDChain& hdChainRet); - void NotifyTransactionLock(const CTransaction &tx) override; - void NotifyChainLock(const CBlockIndex* pindexChainLock) override; + void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) override; + void NotifyChainLock(const CBlockIndex* pindexChainLock, const llmq::CChainLockSig& clsig) override; }; /** A key allocated from the key pool. */ diff --git a/src/zmq/zmqabstractnotifier.cpp b/src/zmq/zmqabstractnotifier.cpp index 72aa19ecbb91..8f61d57429d5 100644 --- a/src/zmq/zmqabstractnotifier.cpp +++ b/src/zmq/zmqabstractnotifier.cpp @@ -16,7 +16,7 @@ bool CZMQAbstractNotifier::NotifyBlock(const CBlockIndex * /*CBlockIndex*/) return true; } -bool CZMQAbstractNotifier::NotifyChainLock(const CBlockIndex * /*CBlockIndex*/) +bool CZMQAbstractNotifier::NotifyChainLock(const CBlockIndex * /*CBlockIndex*/, const llmq::CChainLockSig& /*clsig*/) { return true; } @@ -26,7 +26,7 @@ bool CZMQAbstractNotifier::NotifyTransaction(const CTransaction &/*transaction*/ return true; } -bool CZMQAbstractNotifier::NotifyTransactionLock(const CTransaction &/*transaction*/) +bool CZMQAbstractNotifier::NotifyTransactionLock(const CTransaction &/*transaction*/, const llmq::CInstantSendLock& /*islock*/) { return true; } diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h index 029be2a16171..c29d5919097a 100644 --- a/src/zmq/zmqabstractnotifier.h +++ b/src/zmq/zmqabstractnotifier.h @@ -12,6 +12,11 @@ class CGovernanceObject; class CGovernanceVote; class CZMQAbstractNotifier; +namespace llmq { + class CChainLockSig; + class CInstantSendLock; +} + typedef CZMQAbstractNotifier* (*CZMQNotifierFactory)(); class CZMQAbstractNotifier @@ -35,9 +40,9 @@ class CZMQAbstractNotifier virtual void Shutdown() = 0; virtual bool NotifyBlock(const CBlockIndex *pindex); - virtual bool NotifyChainLock(const CBlockIndex *pindex); + virtual bool NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig); virtual bool NotifyTransaction(const CTransaction &transaction); - virtual bool NotifyTransactionLock(const CTransaction &transaction); + virtual bool NotifyTransactionLock(const CTransaction &transaction, const llmq::CInstantSendLock& islock); virtual bool NotifyGovernanceVote(const CGovernanceVote &vote); virtual bool NotifyGovernanceObject(const CGovernanceObject &object); virtual bool NotifyInstantSendDoubleSpendAttempt(const CTransaction ¤tTx, const CTransaction &previousTx); diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h index c90dc9db8e57..0ce679fdfb63 100644 --- a/src/zmq/zmqconfig.h +++ b/src/zmq/zmqconfig.h @@ -24,6 +24,9 @@ #include "instantsend.h" +#include "llmq/quorums_chainlocks.h" +#include "llmq/quorums_instantsend.h" + void zmqError(const char *str); #endif // BITCOIN_ZMQ_ZMQCONFIG_H diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index a352ab91840e..219c95f65889 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -44,8 +44,10 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create() factories["pubhashinstantsenddoublespend"] = CZMQAbstractNotifier::Create; factories["pubrawblock"] = CZMQAbstractNotifier::Create; factories["pubrawchainlock"] = CZMQAbstractNotifier::Create; + factories["pubrawchainlocksig"] = CZMQAbstractNotifier::Create; factories["pubrawtx"] = CZMQAbstractNotifier::Create; factories["pubrawtxlock"] = CZMQAbstractNotifier::Create; + factories["pubrawtxlocksig"] = CZMQAbstractNotifier::Create; factories["pubrawgovernancevote"] = CZMQAbstractNotifier::Create; factories["pubrawgovernanceobject"] = CZMQAbstractNotifier::Create; factories["pubrawinstantsenddoublespend"] = CZMQAbstractNotifier::Create; @@ -154,12 +156,12 @@ void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, co } } -void CZMQNotificationInterface::NotifyChainLock(const CBlockIndex *pindex) +void CZMQNotificationInterface::NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) { for (std::list::iterator i = notifiers.begin(); i!=notifiers.end(); ) { CZMQAbstractNotifier *notifier = *i; - if (notifier->NotifyChainLock(pindex)) + if (notifier->NotifyChainLock(pindex, clsig)) { i++; } @@ -188,12 +190,12 @@ void CZMQNotificationInterface::SyncTransaction(const CTransaction& tx, const CB } } -void CZMQNotificationInterface::NotifyTransactionLock(const CTransaction &tx) +void CZMQNotificationInterface::NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) { for (std::list::iterator i = notifiers.begin(); i!=notifiers.end(); ) { CZMQAbstractNotifier *notifier = *i; - if (notifier->NotifyTransactionLock(tx)) + if (notifier->NotifyTransactionLock(tx, islock)) { i++; } diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index a94dd29338e4..6a281d09b808 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -26,8 +26,8 @@ class CZMQNotificationInterface : public CValidationInterface // CValidationInterface void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) override; void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; - void NotifyChainLock(const CBlockIndex *pindex) override; - void NotifyTransactionLock(const CTransaction &tx) override; + void NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) override; + void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) override; void NotifyGovernanceVote(const CGovernanceVote& vote) override; void NotifyGovernanceObject(const CGovernanceObject& object) override; void NotifyInstantSendDoubleSpendAttempt(const CTransaction ¤tTx, const CTransaction &previousTx) override; diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 09662d414b3d..6134fde4a986 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -19,8 +19,10 @@ static const char *MSG_HASHGOBJ = "hashgovernanceobject"; static const char *MSG_HASHISCON = "hashinstantsenddoublespend"; static const char *MSG_RAWBLOCK = "rawblock"; static const char *MSG_RAWCHAINLOCK = "rawchainlock"; +static const char *MSG_RAWCLSIG = "rawchainlocksig"; static const char *MSG_RAWTX = "rawtx"; static const char *MSG_RAWTXLOCK = "rawtxlock"; +static const char *MSG_RAWTXLOCKSIG = "rawtxlocksig"; static const char *MSG_RAWGVOTE = "rawgovernancevote"; static const char *MSG_RAWGOBJ = "rawgovernanceobject"; static const char *MSG_RAWISCON = "rawinstantsenddoublespend"; @@ -164,7 +166,7 @@ bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex) return SendMessage(MSG_HASHBLOCK, data, 32); } -bool CZMQPublishHashChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex) +bool CZMQPublishHashChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) { uint256 hash = pindex->GetBlockHash(); LogPrint(BCLog::ZMQ, "zmq: Publish hashchainlock %s\n", hash.GetHex()); @@ -184,7 +186,7 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t return SendMessage(MSG_HASHTX, data, 32); } -bool CZMQPublishHashTransactionLockNotifier::NotifyTransactionLock(const CTransaction &transaction) +bool CZMQPublishHashTransactionLockNotifier::NotifyTransactionLock(const CTransaction &transaction, const llmq::CInstantSendLock& islock) { uint256 hash = transaction.GetHash(); LogPrint(BCLog::ZMQ, "zmq: Publish hashtxlock %s\n", hash.GetHex()); @@ -249,7 +251,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size()); } -bool CZMQPublishRawChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex) +bool CZMQPublishRawChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) { LogPrint(BCLog::ZMQ, "zmq: Publish rawchainlock %s\n", pindex->GetBlockHash().GetHex()); @@ -270,6 +272,28 @@ bool CZMQPublishRawChainLockNotifier::NotifyChainLock(const CBlockIndex *pindex) return SendMessage(MSG_RAWCHAINLOCK, &(*ss.begin()), ss.size()); } +bool CZMQPublishRawChainLockSigNotifier::NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) +{ + LogPrint(BCLog::ZMQ, "zmq: Publish rawchainlocksig %s\n", pindex->GetBlockHash().GetHex()); + + const Consensus::Params& consensusParams = Params().GetConsensus(); + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + { + LOCK(cs_main); + CBlock block; + if(!ReadBlockFromDisk(block, pindex, consensusParams)) + { + zmqError("Can't read block from disk"); + return false; + } + + ss << block; + ss << clsig; + } + + return SendMessage(MSG_RAWCLSIG, &(*ss.begin()), ss.size()); +} + bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction) { uint256 hash = transaction.GetHash(); @@ -279,7 +303,7 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size()); } -bool CZMQPublishRawTransactionLockNotifier::NotifyTransactionLock(const CTransaction &transaction) +bool CZMQPublishRawTransactionLockNotifier::NotifyTransactionLock(const CTransaction &transaction, const llmq::CInstantSendLock& islock) { uint256 hash = transaction.GetHash(); LogPrint(BCLog::ZMQ, "zmq: Publish rawtxlock %s\n", hash.GetHex()); @@ -288,6 +312,16 @@ bool CZMQPublishRawTransactionLockNotifier::NotifyTransactionLock(const CTransac return SendMessage(MSG_RAWTXLOCK, &(*ss.begin()), ss.size()); } +bool CZMQPublishRawTransactionLockSigNotifier::NotifyTransactionLock(const CTransaction &transaction, const llmq::CInstantSendLock& islock) +{ + uint256 hash = transaction.GetHash(); + LogPrint(BCLog::ZMQ, "zmq: Publish rawtxlocksig %s\n", hash.GetHex()); + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << transaction; + ss << islock; + return SendMessage(MSG_RAWTXLOCKSIG, &(*ss.begin()), ss.size()); +} + bool CZMQPublishRawGovernanceVoteNotifier::NotifyGovernanceVote(const CGovernanceVote &vote) { uint256 nHash = vote.GetHash(); diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index eaf7e2d59232..7b64d30f73bf 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -39,7 +39,7 @@ class CZMQPublishHashBlockNotifier : public CZMQAbstractPublishNotifier class CZMQPublishHashChainLockNotifier : public CZMQAbstractPublishNotifier { public: - bool NotifyChainLock(const CBlockIndex *pindex) override; + bool NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) override; }; class CZMQPublishHashTransactionNotifier : public CZMQAbstractPublishNotifier @@ -51,7 +51,7 @@ class CZMQPublishHashTransactionNotifier : public CZMQAbstractPublishNotifier class CZMQPublishHashTransactionLockNotifier : public CZMQAbstractPublishNotifier { public: - bool NotifyTransactionLock(const CTransaction &transaction) override; + bool NotifyTransactionLock(const CTransaction &transaction, const llmq::CInstantSendLock& islock) override; }; class CZMQPublishHashGovernanceVoteNotifier : public CZMQAbstractPublishNotifier @@ -81,7 +81,13 @@ class CZMQPublishRawBlockNotifier : public CZMQAbstractPublishNotifier class CZMQPublishRawChainLockNotifier : public CZMQAbstractPublishNotifier { public: - bool NotifyChainLock(const CBlockIndex *pindex) override; + bool NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) override; +}; + +class CZMQPublishRawChainLockSigNotifier : public CZMQAbstractPublishNotifier +{ +public: + bool NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) override; }; class CZMQPublishRawTransactionNotifier : public CZMQAbstractPublishNotifier @@ -93,7 +99,13 @@ class CZMQPublishRawTransactionNotifier : public CZMQAbstractPublishNotifier class CZMQPublishRawTransactionLockNotifier : public CZMQAbstractPublishNotifier { public: - bool NotifyTransactionLock(const CTransaction &transaction) override; + bool NotifyTransactionLock(const CTransaction &transaction, const llmq::CInstantSendLock& islock) override; +}; + +class CZMQPublishRawTransactionLockSigNotifier : public CZMQAbstractPublishNotifier +{ +public: + bool NotifyTransactionLock(const CTransaction &transaction, const llmq::CInstantSendLock& islock) override; }; class CZMQPublishRawGovernanceVoteNotifier : public CZMQAbstractPublishNotifier From 55d1251ffcd0b404f0bb08b3b9599ac6a6e0b76e Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 13 Apr 2017 09:54:05 -0700 Subject: [PATCH 090/987] Merge #9480: De-duplicate SignatureCacheHasher f9c8807 Deduplicate SignatureCacheHasher (Jeremy Rubin) Tree-SHA512: 714a0f39d1c836fedd1868369b4ebf1096cd800cc544d57b54101da338c80c627a3e59c6644b3268054efe85053cf1a7be508af935f624491e7acfae61123994 --- src/script/sigcache.cpp | 22 ---------------------- src/script/sigcache.h | 21 +++++++++++++++++++++ src/test/cuckoocache_tests.cpp | 25 ++++++------------------- 3 files changed, 27 insertions(+), 41 deletions(-) diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index e3861d14a03f..4303920caff6 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -15,28 +15,6 @@ #include namespace { - -/** - * We're hashing a nonce into the entries themselves, so we don't need extra - * blinding in the set hash computation. - * - * This may exhibit platform endian dependent behavior but because these are - * nonced hashes (random) and this state is only ever used locally it is safe. - * All that matters is local consistency. - */ -class SignatureCacheHasher -{ -public: - template - uint32_t operator()(const uint256& key) const - { - static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available."); - uint32_t u; - std::memcpy(&u, key.begin()+4*hash_select, 4); - return u; - } -}; - /** * Valid signature cache, to avoid doing expensive ECDSA signature checking * twice for every transaction (once when accepted into memory pool, and diff --git a/src/script/sigcache.h b/src/script/sigcache.h index 15ee161deffe..d956ba10dd85 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -19,6 +19,27 @@ static const int64_t MAX_MAX_SIG_CACHE_SIZE = 16384; class CPubKey; +/** + * We're hashing a nonce into the entries themselves, so we don't need extra + * blinding in the set hash computation. + * + * This may exhibit platform endian dependent behavior but because these are + * nonced hashes (random) and this state is only ever used locally it is safe. + * All that matters is local consistency. + */ +class SignatureCacheHasher +{ +public: + template + uint32_t operator()(const uint256& key) const + { + static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available."); + uint32_t u; + std::memcpy(&u, key.begin()+4*hash_select, 4); + return u; + } +}; + class CachingTransactionSignatureChecker : public TransactionSignatureChecker { private: diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 15b128bef7ce..8a1196870c4d 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include "cuckoocache.h" +#include "script/sigcache.h" #include "test/test_dash.h" #include "random.h" #include @@ -36,20 +37,6 @@ void insecure_GetRandHash(uint256& t) *(ptr++) = insecure_rand.rand32(); } -/** Definition copied from /src/script/sigcache.cpp - */ -class uint256Hasher -{ -public: - template - uint32_t operator()(const uint256& key) const - { - static_assert(hash_select <8, "SignatureCacheHasher only has 8 hashes available."); - uint32_t u; - std::memcpy(&u, key.begin() + 4 * hash_select, 4); - return u; - } -}; /* Test that no values not inserted into the cache are read out of it. @@ -59,7 +46,7 @@ class uint256Hasher BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) { insecure_rand = FastRandomContext(true); - CuckooCache::cache cc{}; + CuckooCache::cache cc{}; size_t megabytes = 4; cc.setup_bytes(megabytes << 20); uint256 v; @@ -138,7 +125,7 @@ BOOST_AUTO_TEST_CASE(cuckoocache_hit_rate_ok) double HitRateThresh = 0.98; size_t megabytes = 4; for (double load = 0.1; load < 2; load *= 2) { - double hits = test_cache>(megabytes, load); + double hits = test_cache>(megabytes, load); BOOST_CHECK(normalize_hit_rate(hits, load) > HitRateThresh); } } @@ -206,7 +193,7 @@ void test_cache_erase(size_t megabytes) BOOST_AUTO_TEST_CASE(cuckoocache_erase_ok) { size_t megabytes = 4; - test_cache_erase>(megabytes); + test_cache_erase>(megabytes); } template @@ -293,7 +280,7 @@ void test_cache_erase_parallel(size_t megabytes) BOOST_AUTO_TEST_CASE(cuckoocache_erase_parallel_ok) { size_t megabytes = 4; - test_cache_erase_parallel>(megabytes); + test_cache_erase_parallel>(megabytes); } @@ -389,7 +376,7 @@ void test_cache_generations() } BOOST_AUTO_TEST_CASE(cuckoocache_generations) { - test_cache_generations>(); + test_cache_generations>(); } BOOST_AUTO_TEST_SUITE_END(); From 0b232fd1cff3c30e9fc344ee3e803de7ef5cae89 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 18 Apr 2017 07:54:56 +0200 Subject: [PATCH 091/987] Merge #10208: [wallet] Rescan abortability 9141622 [rpc] Add abortrescan command to RPC interface. (Kalle Alm) 75a08e7 [wallet] Add support for aborting wallet transaction rescans. (Kalle Alm) Tree-SHA512: 18545a1dc48c6dc112993f971f3adc7c0341fa621186c6d70bef1052e1d127ca116c5769595d721a209d502ca2019f2ad33876fe35d2b17216393404607a6c76 --- src/wallet/rpcdump.cpp | 25 +++++++++++++++++++++++++ src/wallet/rpcwallet.cpp | 2 ++ src/wallet/wallet.cpp | 9 ++++++++- src/wallet/wallet.h | 11 +++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index a50abea43623..2ead3d72d4c3 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -157,6 +157,31 @@ UniValue importprivkey(const JSONRPCRequest& request) return NullUniValue; } +UniValue abortrescan(const JSONRPCRequest& request) +{ + CWallet* const pwallet = GetWalletForJSONRPCRequest(request); + if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { + return NullUniValue; + } + + if (request.fHelp || request.params.size() > 0) + throw std::runtime_error( + "abortrescan\n" + "\nStops current wallet rescan triggered e.g. by an importprivkey call.\n" + "\nExamples:\n" + "\nImport a private key\n" + + HelpExampleCli("importprivkey", "\"mykey\"") + + "\nAbort the running wallet rescan\n" + + HelpExampleCli("abortrescan", "") + + "\nAs a JSON-RPC call\n" + + HelpExampleRpc("abortrescan", "") + ); + + if (!pwallet->IsScanning() || pwallet->IsAbortingRescan()) return false; + pwallet->AbortRescan(); + return true; +} + void ImportAddress(CWallet*, const CBitcoinAddress& address, const std::string& strLabel); void ImportScript(CWallet * const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7bc9ddd2f661..c221cbed5204 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2998,6 +2998,7 @@ UniValue setbip69enabled(const JSONRPCRequest& request) return NullUniValue; } +extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp extern UniValue importprivkey(const JSONRPCRequest& request); extern UniValue importaddress(const JSONRPCRequest& request); @@ -3017,6 +3018,7 @@ static const CRPCCommand commands[] = { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false, {"hexstring","options"} }, { "hidden", "resendwallettransactions", &resendwallettransactions, true, {} }, { "wallet", "abandontransaction", &abandontransaction, false, {"txid"} }, + { "wallet", "abortrescan", &abortrescan, false, {} }, { "wallet", "addmultisigaddress", &addmultisigaddress, true, {"nrequired","keys","account"} }, { "wallet", "backupwallet", &backupwallet, true, {"destination"} }, { "wallet", "dumpprivkey", &dumpprivkey, true, {"address"} }, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ea8d78f94c88..2209fbfae543 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1835,6 +1835,8 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f CBlockIndex* ret = pindexStart; { LOCK2(cs_main, cs_wallet); + fAbortRescan = false; + fScanningWallet = true; // no need to read and scan block, if block was created before // our wallet birthday (as adjusted for block time variability) @@ -1844,7 +1846,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup double dProgressStart = GuessVerificationProgress(chainParams.TxData(), pindex); double dProgressTip = GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()); - while (pindex) + while (pindex && !fAbortRescan) { if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0) ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((GuessVerificationProgress(chainParams.TxData(), pindex) - dProgressStart) / (dProgressTip - dProgressStart) * 100)))); @@ -1866,7 +1868,12 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f } pindex = chainActive.Next(pindex); } + if (pindex && fAbortRescan) { + LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, GuessVerificationProgress(chainParams.TxData(), pindex)); + } ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI + + fScanningWallet = false; } return ret; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b5543aa8d66c..4b57a1128f99 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -673,6 +673,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface { private: static std::atomic fFlushScheduled; + std::atomic fAbortRescan; + std::atomic fScanningWallet; /** * Select a set of coins such that nValueRet >= nTargetValue and at least @@ -804,6 +806,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface nTimeFirstKey = 0; fBroadcastTransactions = false; nRelockTime = 0; + fAbortRescan = false; + fScanningWallet = false; fAnonymizableTallyCached = false; fAnonymizableTallyCachedNonDenom = false; vecAnonymizableTallyCached.clear(); @@ -879,6 +883,13 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void ListLockedCoins(std::vector& vOutpts); void ListProTxCoins(std::vector& vOutpts); + /* + * Rescan abort properties + */ + void AbortRescan() { fAbortRescan = true; } + bool IsAbortingRescan() { return fAbortRescan; } + bool IsScanning() { return fScanningWallet; } + /** * keystore implementation * Generate a new key From 7fa60a1c73f152f9aaf956c6656af8ae4210fc2a Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 18 Apr 2017 09:25:36 +0200 Subject: [PATCH 092/987] Merge #10219: Tests: Order Python Tests Differently 637706d Tests: Put Extended tests first when they're included (Jimmy Song) Tree-SHA512: 0a720b2443b3e65f4ad548ecdf822468460fc4f4ecf32385dd79511a01c9ea4c94f0bf765ca593705b19baee1bae254dfcc3952da64b9c51d75b7da7abcdcd28 --- test/README.md | 2 ++ test/functional/test_runner.py | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/test/README.md b/test/README.md index aaaa0406c4fb..dd258dd08698 100644 --- a/test/README.md +++ b/test/README.md @@ -25,6 +25,8 @@ The ZMQ functional test requires a python ZMQ library. To install it: Running tests locally ===================== +Build for your system first. Be sure to enable wallet, utils and daemon when you configure. Tests will not run otherwise. + Functional tests ---------------- diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 89ff1e5fb747..9a0ddfc5de66 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -140,7 +140,8 @@ 'p2p-acceptblock.py', # NOTE: needs dash_hash to pass ] -ALL_SCRIPTS = BASE_SCRIPTS + ZMQ_SCRIPTS + EXTENDED_SCRIPTS +# Place EXTENDED_SCRIPTS first since it has the 3 longest running tests +ALL_SCRIPTS = EXTENDED_SCRIPTS + BASE_SCRIPTS + ZMQ_SCRIPTS NON_SCRIPTS = [ # These are python files that live in the functional tests directory, but are not test scripts. @@ -212,10 +213,9 @@ def main(): if enable_zmq: test_list += ZMQ_SCRIPTS if args.extended: - test_list += EXTENDED_SCRIPTS - # TODO: BASE_SCRIPTS and EXTENDED_SCRIPTS are sorted by runtime - # (for parallel running efficiency). This combined list will is no - # longer sorted. + # place the EXTENDED_SCRIPTS first since the three longest ones + # are there and the list is shorter + test_list = EXTENDED_SCRIPTS + test_list # Remove the test cases that the user has explicitly asked to exclude. if args.exclude: From 16053cd528a1ee3ee0b666b546b1023aa7ea45f6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 19 Apr 2017 10:50:59 +0200 Subject: [PATCH 093/987] Merge #10226: wallet: Use boost to more portably ensure -wallet specifies only a filename a4186dd wallet: Use boost to more portably ensure -wallet specifies only a filename (Luke Dashjr) Tree-SHA512: 6dfde31fa599638e5ec76489363e2fed97403be3e5762e4560dfc6ac261ce169a92b5a1b92bb34a893cc898e6073c81f74f49528e8df07e86273ddb37dd1ce80 --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 2209fbfae543..0f9c462d6ee9 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5018,7 +5018,7 @@ bool CWallet::InitLoadWallet() std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); - if (walletFile.find_first_of("/\\") != std::string::npos) { + if (boost::filesystem::path(walletFile).filename() != walletFile) { return InitError(_("-wallet parameter must only specify a filename (not a path)")); } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { return InitError(_("Invalid characters in -wallet filename")); From 4efa99c2df8fa56af45aade4d16a419f75998334 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 19 Apr 2017 11:14:21 +0200 Subject: [PATCH 094/987] Merge #10221: Stop treating coinbase outputs differently in GUI: show them at 1conf 608bbcc [qt] Stop treating coinbase outputs differently: show them at 1conf (Matt Corallo) Tree-SHA512: 62ba10520da8b83cf8e97c86dec3ccdcca8b7bfae0174d1a4099d33aa5d11933cc7c248394bf67c2b105211cf7931955816c741957832e703211030c7f4f002f --- src/qt/transactionrecord.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 88e1bcfd555a..aee7720f8196 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -21,14 +21,8 @@ */ bool TransactionRecord::showTransaction(const CWalletTx &wtx) { - if (wtx.IsCoinBase()) - { - // Ensures we show generated coins / mined transactions at depth 1 - if (!wtx.IsInMainChain()) - { - return false; - } - } + // There are currently no cases where we hide transactions, but + // we may want to use this in the future for things like RBF. return true; } From 6f558270d4bfff844c837166dd5cf3276eaf4a84 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 20 Apr 2017 11:46:37 +0200 Subject: [PATCH 095/987] Merge #10143: [net] Allow disconnectnode RPC to be called with node id d54297f [tests] disconnect_ban: add tests for disconnect-by-nodeid (John Newbery) 5cc3ee2 [tests] disconnect_ban: remove dependency on urllib (John Newbery) 12de2f2 [tests] disconnect_ban: use wait_until instead of sleep (John Newbery) 2077fda [tests] disconnect_ban: add logging (John Newbery) 395561b [tests] disconnectban test - only use two nodes (John Newbery) e367ad5 [tests] rename nodehandling to disconnectban (John Newbery) d6564a2 [tests] fix nodehandling.py flake8 warnings (John Newbery) 23e6e64 Allow disconnectnode() to be called with node id (John Newbery) Tree-SHA512: a371bb05a24a91cdb16a7ac4fbb091d5d3bf6554b29bd69d74522cb7523d3f1c5b1989d5e7b03f3fc7369fb727098dd2a549de551b731dd480c121d9517d3576 --- src/rpc/client.cpp | 1 + src/rpc/net.cpp | 34 ++++++++-- test/functional/disconnect_ban.py | 109 ++++++++++++++++++++++++++++++ test/functional/nodehandling.py | 81 ---------------------- test/functional/test_runner.py | 2 +- 5 files changed, 138 insertions(+), 89 deletions(-) create mode 100755 test/functional/disconnect_ban.py diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index cc04555e469b..03cdd9cda11a 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -158,6 +158,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getspecialtxes", 2, "count" }, { "getspecialtxes", 3, "skip" }, { "getspecialtxes", 4, "verbosity" }, + { "disconnectnode", 1, "nodeid" }, // Echo with conversion (For testing only) { "echojson", 0, "arg0" }, { "echojson", 1, "arg1" }, diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 1828a8a9652f..458771fd4aaf 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -235,23 +235,43 @@ UniValue addnode(const JSONRPCRequest& request) UniValue disconnectnode(const JSONRPCRequest& request) { - if (request.fHelp || request.params.size() != 1) + if (request.fHelp || request.params.size() == 0 || request.params.size() >= 3) throw std::runtime_error( - "disconnectnode \"address\" \n" - "\nImmediately disconnects from the specified node.\n" + "disconnectnode \"[address]\" [nodeid]\n" + "\nImmediately disconnects from the specified peer node.\n" + "\nStrictly one out of 'address' and 'nodeid' can be provided to identify the node.\n" + "\nTo disconnect by nodeid, either set 'address' to the empty string, or call using the named 'nodeid' argument only.\n" "\nArguments:\n" - "1. \"address\" (string, required) The IP address/port of the node\n" + "1. \"address\" (string, optional) The IP address/port of the node\n" + "2. \"nodeid\" (number, optional) The node ID (see getpeerinfo for node IDs)\n" "\nExamples:\n" + HelpExampleCli("disconnectnode", "\"192.168.0.6:9999\"") + + HelpExampleCli("disconnectnode", "\"\" 1") + HelpExampleRpc("disconnectnode", "\"192.168.0.6:9999\"") + + HelpExampleRpc("disconnectnode", "\"\", 1") ); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); - bool ret = g_connman->DisconnectNode(request.params[0].get_str()); - if (!ret) + bool success; + const UniValue &address_arg = request.params[0]; + const UniValue &id_arg = request.params.size() < 2 ? NullUniValue : request.params[1]; + + if (!address_arg.isNull() && id_arg.isNull()) { + /* handle disconnect-by-address */ + success = g_connman->DisconnectNode(address_arg.get_str()); + } else if (!id_arg.isNull() && (address_arg.isNull() || (address_arg.isStr() && address_arg.get_str().empty()))) { + /* handle disconnect-by-id */ + NodeId nodeid = (NodeId) id_arg.get_int64(); + success = g_connman->DisconnectNode(nodeid); + } else { + throw JSONRPCError(RPC_INVALID_PARAMS, "Only one of address and nodeid should be provided."); + } + + if (!success) { throw JSONRPCError(RPC_CLIENT_NODE_NOT_CONNECTED, "Node not found in connected nodes"); + } return NullUniValue; } @@ -608,7 +628,7 @@ static const CRPCCommand commands[] = { "network", "ping", &ping, true, {} }, { "network", "getpeerinfo", &getpeerinfo, true, {} }, { "network", "addnode", &addnode, true, {"node","command"} }, - { "network", "disconnectnode", &disconnectnode, true, {"address"} }, + { "network", "disconnectnode", &disconnectnode, true, {"address", "nodeid"} }, { "network", "getaddednodeinfo", &getaddednodeinfo, true, {"node"} }, { "network", "getnettotals", &getnettotals, true, {} }, { "network", "getnetworkinfo", &getnetworkinfo, true, {} }, diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py new file mode 100755 index 000000000000..3f451d49d23e --- /dev/null +++ b/test/functional/disconnect_ban.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test node disconnect and ban behavior""" + +from test_framework.mininode import wait_until +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import (assert_equal, + assert_raises_jsonrpc, + connect_nodes_bi, + start_node, + stop_node, + ) + +class DisconnectBanTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 2 + self.setup_clean_chain = False + + def setup_network(self): + self.nodes = self.setup_nodes() + connect_nodes_bi(self.nodes, 0, 1) + + def run_test(self): + self.log.info("Test setban and listbanned RPCs") + + self.log.info("setban: successfully ban single IP address") + assert_equal(len(self.nodes[1].getpeerinfo()), 2) # node1 should have 2 connections to node0 at this point + self.nodes[1].setban("127.0.0.1", "add") + wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0) + assert_equal(len(self.nodes[1].getpeerinfo()), 0) # all nodes must be disconnected at this point + assert_equal(len(self.nodes[1].listbanned()), 1) + + self.log.info("clearbanned: successfully clear ban list") + self.nodes[1].clearbanned() + assert_equal(len(self.nodes[1].listbanned()), 0) + self.nodes[1].setban("127.0.0.0/24", "add") + + self.log.info("setban: fail to ban an already banned subnet") + assert_equal(len(self.nodes[1].listbanned()), 1) + assert_raises_jsonrpc(-23, "IP/Subnet already banned", self.nodes[1].setban, "127.0.0.1", "add") + + self.log.info("setban: fail to ban an invalid subnet") + assert_raises_jsonrpc(-30, "Error: Invalid IP/Subnet", self.nodes[1].setban, "127.0.0.1/42", "add") + assert_equal(len(self.nodes[1].listbanned()), 1) # still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24 + + self.log.info("setban remove: fail to unban a non-banned subnet") + assert_raises_jsonrpc(-30, "Error: Unban failed", self.nodes[1].setban, "127.0.0.1", "remove") + assert_equal(len(self.nodes[1].listbanned()), 1) + + self.log.info("setban remove: successfully unban subnet") + self.nodes[1].setban("127.0.0.0/24", "remove") + assert_equal(len(self.nodes[1].listbanned()), 0) + self.nodes[1].clearbanned() + assert_equal(len(self.nodes[1].listbanned()), 0) + + self.log.info("setban: test persistence across node restart") + self.nodes[1].setban("127.0.0.0/32", "add") + self.nodes[1].setban("127.0.0.0/24", "add") + self.nodes[1].setban("192.168.0.1", "add", 1) # ban for 1 seconds + self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) # ban for 1000 seconds + listBeforeShutdown = self.nodes[1].listbanned() + assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) + wait_until(lambda: len(self.nodes[1].listbanned()) == 3) + + stop_node(self.nodes[1], 1) + + self.nodes[1] = start_node(1, self.options.tmpdir) + listAfterShutdown = self.nodes[1].listbanned() + assert_equal("127.0.0.0/24", listAfterShutdown[0]['address']) + assert_equal("127.0.0.0/32", listAfterShutdown[1]['address']) + assert_equal("/19" in listAfterShutdown[2]['address'], True) + + # Clear ban lists + self.nodes[1].clearbanned() + connect_nodes_bi(self.nodes, 0, 1) + + self.log.info("Test disconnectrnode RPCs") + + self.log.info("disconnectnode: fail to disconnect when calling with address and nodeid") + address1 = self.nodes[0].getpeerinfo()[0]['addr'] + node1 = self.nodes[0].getpeerinfo()[0]['addr'] + assert_raises_jsonrpc(-32602, "Only one of address and nodeid should be provided.", self.nodes[0].disconnectnode, address=address1, nodeid=node1) + + self.log.info("disconnectnode: fail to disconnect when calling with junk address") + assert_raises_jsonrpc(-29, "Node not found in connected nodes", self.nodes[0].disconnectnode, address="221B Baker Street") + + self.log.info("disconnectnode: successfully disconnect node by address") + address1 = self.nodes[0].getpeerinfo()[0]['addr'] + self.nodes[0].disconnectnode(address=address1) + wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1) + assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1] + + self.log.info("disconnectnode: successfully reconnect node") + connect_nodes_bi(self.nodes, 0, 1) # reconnect the node + assert_equal(len(self.nodes[0].getpeerinfo()), 2) + assert [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1] + + self.log.info("disconnectnode: successfully disconnect node by node id") + id1 = self.nodes[0].getpeerinfo()[0]['id'] + self.nodes[0].disconnectnode(nodeid=id1) + wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1) + assert not [node for node in self.nodes[0].getpeerinfo() if node['id'] == id1] + +if __name__ == '__main__': + DisconnectBanTest().main() diff --git a/test/functional/nodehandling.py b/test/functional/nodehandling.py index f6776b336361..e69de29bb2d1 100755 --- a/test/functional/nodehandling.py +++ b/test/functional/nodehandling.py @@ -1,81 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2014-2016 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test node handling.""" - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * - -import urllib.parse - -class NodeHandlingTest (BitcoinTestFramework): - - def __init__(self): - super().__init__() - self.num_nodes = 4 - self.setup_clean_chain = False - - def run_test(self): - ########################### - # setban/listbanned tests # - ########################### - assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point - self.nodes[2].setban("127.0.0.1", "add") - time.sleep(3) #wait till the nodes are disconected - assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point - assert_equal(len(self.nodes[2].listbanned()), 1) - self.nodes[2].clearbanned() - assert_equal(len(self.nodes[2].listbanned()), 0) - self.nodes[2].setban("127.0.0.0/24", "add") - assert_equal(len(self.nodes[2].listbanned()), 1) - # This will throw an exception because 127.0.0.1 is within range 127.0.0.0/24 - assert_raises_jsonrpc(-23, "IP/Subnet already banned", self.nodes[2].setban, "127.0.0.1", "add") - # This will throw an exception because 127.0.0.1/42 is not a real subnet - assert_raises_jsonrpc(-30, "Error: Invalid IP/Subnet", self.nodes[2].setban, "127.0.0.1/42", "add") - assert_equal(len(self.nodes[2].listbanned()), 1) #still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24 - # This will throw an exception because 127.0.0.1 was not added above - assert_raises_jsonrpc(-30, "Error: Unban failed", self.nodes[2].setban, "127.0.0.1", "remove") - assert_equal(len(self.nodes[2].listbanned()), 1) - self.nodes[2].setban("127.0.0.0/24", "remove") - assert_equal(len(self.nodes[2].listbanned()), 0) - self.nodes[2].clearbanned() - assert_equal(len(self.nodes[2].listbanned()), 0) - - ##test persisted banlist - self.nodes[2].setban("127.0.0.0/32", "add") - self.nodes[2].setban("127.0.0.0/24", "add") - self.nodes[2].setban("192.168.0.1", "add", 1) #ban for 1 seconds - self.nodes[2].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) #ban for 1000 seconds - listBeforeShutdown = self.nodes[2].listbanned() - assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) #must be here - set_mocktime(get_mocktime() + 2) #make 100% sure we expired 192.168.0.1 node time - set_node_times(self.nodes, get_mocktime()) #make 100% sure we expired 192.168.0.1 node time - - #stop node - stop_node(self.nodes[2], 2) - - self.nodes[2] = start_node(2, self.options.tmpdir) - listAfterShutdown = self.nodes[2].listbanned() - assert_equal("127.0.0.0/24", listAfterShutdown[0]['address']) - assert_equal("127.0.0.0/32", listAfterShutdown[1]['address']) - assert_equal("/19" in listAfterShutdown[2]['address'], True) - - ########################### - # RPC disconnectnode test # - ########################### - url = urllib.parse.urlparse(self.nodes[1].url) - self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1))) - time.sleep(2) #disconnecting a node needs a little bit of time - for node in self.nodes[0].getpeerinfo(): - assert(node['addr'] != url.hostname+":"+str(p2p_port(1))) - - connect_nodes_bi(self.nodes,0,1) #reconnect the node - found = False - for node in self.nodes[0].getpeerinfo(): - if node['addr'] == url.hostname+":"+str(p2p_port(1)): - found = True - assert(found) - -if __name__ == '__main__': - NodeHandlingTest ().main () diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 9a0ddfc5de66..13eb97bcdaa3 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -75,7 +75,7 @@ 'multi_rpc.py', 'proxy_test.py', 'signrawtransactions.py', - 'nodehandling.py', + 'disconnect_ban.py', 'addressindex.py', 'timestampindex.py', 'spentindex.py', From c8a565d6e66259c2d3f3ab12eb6e3b4fdce7adb4 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 31 Mar 2017 09:26:33 +0200 Subject: [PATCH 096/987] Merge #10090: Update bitcoin.conf with example for pruning c0651cc Update bitcoin.conf with example for pruning (Kyle Honeycutt) Tree-SHA512: f27180ac5d5a4bd32c7a63de156ca14eb8068509e64d386ca84ee16d0dacfa8e1bab9a8e7b88175fae12c8d823f71f8705d413f224a15d5aa7cf059f416fa023 --- contrib/debian/examples/dash.conf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/contrib/debian/examples/dash.conf b/contrib/debian/examples/dash.conf index 2ea173018440..6f5b31255670 100644 --- a/contrib/debian/examples/dash.conf +++ b/contrib/debian/examples/dash.conf @@ -131,6 +131,13 @@ # be validated sooner. #paytxfee=0.00 +# Enable pruning to reduce storage requirements by deleting old blocks. +# This mode is incompatible with -txindex and -rescan. +# 0 = default (no pruning). +# 1 = allows manual pruning via RPC. +# >=550 = target to stay under in MiB. +#prune=550 + # User interface options # Start Dash minimized From 515343963325e4ef6731454c2207f98f0dbb2ad6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 2 Apr 2017 09:27:56 +0200 Subject: [PATCH 097/987] Merge #10036: Fix init README format to render correctly on github b99fbad Fix init README format to render correctly on github (Jameson Lopp) Tree-SHA512: 52b8ed9661e48e830c9e0c0e9aa670fe8d1a3848426d2d854494b477a9926f286d87e0586c2bc63f433136f8e5acd2cab3ab1f616380fb517c5a8f9d34ed52da --- contrib/init/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/init/README.md b/contrib/init/README.md index 8bda937e2a3a..e0adc72f3df4 100644 --- a/contrib/init/README.md +++ b/contrib/init/README.md @@ -1,12 +1,12 @@ Sample configuration files for: - +``` SystemD: dashd.service Upstart: dashd.conf OpenRC: dashd.openrc dashd.openrcconf CentOS: dashd.init OS X: org.dash.dashd.plist - +``` have been made available to assist packagers in creating node packages here. See doc/init.md for more information. From a54ff70ff42eaf65bab963dcad1c5fd0af4ca816 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 6 Apr 2017 20:19:21 +0200 Subject: [PATCH 098/987] Merge #9902: Lightweight abstraction of boost::filesystem f110272 Remove `namespace fs=fs` (Wladimir J. van der Laan) 75594bd torcontrol: Use fs::path instead of std::string for private key path (Wladimir J. van der Laan) 2a5f574 Use fsbridge for fopen and freopen (Wladimir J. van der Laan) bac5c9c Replace uses of boost::filesystem with fs (Wladimir J. van der Laan) 7d5172d Replace includes of boost/filesystem.h with fs.h (Wladimir J. van der Laan) 19e36bb Add fs.cpp/h (Wladimir J. van der Laan) Tree-SHA512: 2c34f059dfa6850b9323f3389e9090a6b5f839a457a2960d182c2ecfafd9883c956f5928bb796613402d3aad68ebc78259796a7a313f4a6cfa98aaf507a66842 --- src/Makefile.am | 2 + src/addrdb.cpp | 18 ++++----- src/addrdb.h | 6 +-- src/dash-cli.cpp | 4 +- src/dashd.cpp | 4 +- src/dbwrapper.cpp | 5 +-- src/dbwrapper.h | 3 +- src/fs.cpp | 17 +++++++++ src/fs.h | 24 ++++++++++++ src/init.cpp | 46 +++++++++++------------ src/net.h | 2 +- src/qt/dash.cpp | 4 +- src/qt/guiutil.cpp | 52 ++++++++++++-------------- src/qt/guiutil.h | 7 ++-- src/qt/intro.cpp | 5 +-- src/qt/test/rpcnestedtests.cpp | 5 +-- src/rpc/protocol.cpp | 12 +++--- src/rpc/protocol.h | 5 ++- src/rpc/server.cpp | 2 +- src/test/dbwrapper_tests.cpp | 18 ++++----- src/test/test_dash.cpp | 6 +-- src/test/test_dash.h | 4 +- src/test/testutil.cpp | 6 +-- src/test/testutil.h | 4 +- src/torcontrol.cpp | 20 +++++----- src/util.cpp | 67 ++++++++++++++++------------------ src/util.h | 18 ++++----- src/validation.cpp | 23 ++++++------ src/validation.h | 4 +- src/wallet/db.cpp | 28 +++++++------- src/wallet/db.h | 11 +++--- src/wallet/wallet.cpp | 12 +++--- src/wallet/walletdb.cpp | 6 +-- src/wallet/walletdb.h | 4 +- 34 files changed, 241 insertions(+), 213 deletions(-) create mode 100644 src/fs.cpp create mode 100644 src/fs.h diff --git a/src/Makefile.am b/src/Makefile.am index c648575cb316..38f5077a4e78 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -154,6 +154,7 @@ BITCOIN_CORE_H = \ governance/governance-votedb.h \ flat-database.h \ hdchain.h \ + fs.h \ httprpc.h \ httpserver.h \ indirectmap.h \ @@ -494,6 +495,7 @@ libdash_util_a_SOURCES = \ compat/glibc_sanity.cpp \ compat/glibcxx_sanity.cpp \ compat/strnlen.cpp \ + fs.cpp \ random.cpp \ rpc/protocol.cpp \ stacktraces.cpp \ diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 23715bbea466..dce52aea6ae6 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -8,13 +8,13 @@ #include "addrman.h" #include "chainparams.h" #include "clientversion.h" +#include "fs.h" #include "hash.h" #include "random.h" #include "streams.h" #include "tinyformat.h" #include "util.h" -#include CBanDB::CBanDB() { @@ -36,8 +36,8 @@ bool CBanDB::Write(const banmap_t& banSet) ssBanlist << hash; // open temp output file, and associate with CAutoFile - boost::filesystem::path pathTmp = GetDataDir() / tmpfn; - FILE *file = fopen(pathTmp.string().c_str(), "wb"); + fs::path pathTmp = GetDataDir() / tmpfn; + FILE *file = fsbridge::fopen(pathTmp, "wb"); CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); if (fileout.IsNull()) return error("%s: Failed to open file %s", __func__, pathTmp.string()); @@ -62,13 +62,13 @@ bool CBanDB::Write(const banmap_t& banSet) bool CBanDB::Read(banmap_t& banSet) { // open input file, and associate with CAutoFile - FILE *file = fopen(pathBanlist.string().c_str(), "rb"); + FILE *file = fsbridge::fopen(pathBanlist, "rb"); CAutoFile filein(file, SER_DISK, CLIENT_VERSION); if (filein.IsNull()) return error("%s: Failed to open file %s", __func__, pathBanlist.string()); // use file size to size memory buffer - uint64_t fileSize = boost::filesystem::file_size(pathBanlist); + uint64_t fileSize = fs::file_size(pathBanlist); uint64_t dataSize = 0; // Don't try to resize to a negative number if file is small if (fileSize >= sizeof(uint256)) @@ -133,8 +133,8 @@ bool CAddrDB::Write(const CAddrMan& addr) ssPeers << hash; // open temp output file, and associate with CAutoFile - boost::filesystem::path pathTmp = GetDataDir() / tmpfn; - FILE *file = fopen(pathTmp.string().c_str(), "wb"); + fs::path pathTmp = GetDataDir() / tmpfn; + FILE *file = fsbridge::fopen(pathTmp, "wb"); CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); if (fileout.IsNull()) return error("%s: Failed to open file %s", __func__, pathTmp.string()); @@ -159,13 +159,13 @@ bool CAddrDB::Write(const CAddrMan& addr) bool CAddrDB::Read(CAddrMan& addr) { // open input file, and associate with CAutoFile - FILE *file = fopen(pathAddr.string().c_str(), "rb"); + FILE *file = fsbridge::fopen(pathAddr, "rb"); CAutoFile filein(file, SER_DISK, CLIENT_VERSION); if (filein.IsNull()) return error("%s: Failed to open file %s", __func__, pathAddr.string()); // use file size to size memory buffer - uint64_t fileSize = boost::filesystem::file_size(pathAddr); + uint64_t fileSize = fs::file_size(pathAddr); uint64_t dataSize = 0; // Don't try to resize to a negative number if file is small if (fileSize >= sizeof(uint256)) diff --git a/src/addrdb.h b/src/addrdb.h index 339943ca5af3..afb62c580ad2 100644 --- a/src/addrdb.h +++ b/src/addrdb.h @@ -6,11 +6,11 @@ #ifndef BITCOIN_ADDRDB_H #define BITCOIN_ADDRDB_H +#include "fs.h" #include "serialize.h" #include #include -#include class CSubNet; class CAddrMan; @@ -80,7 +80,7 @@ typedef std::map banmap_t; class CAddrDB { private: - boost::filesystem::path pathAddr; + fs::path pathAddr; public: CAddrDB(); bool Write(const CAddrMan& addr); @@ -92,7 +92,7 @@ class CAddrDB class CBanDB { private: - boost::filesystem::path pathBanlist; + fs::path pathBanlist; public: CBanDB(); bool Write(const banmap_t& banSet); diff --git a/src/dash-cli.cpp b/src/dash-cli.cpp index 818b4de4caee..b9fb7b777d85 100644 --- a/src/dash-cli.cpp +++ b/src/dash-cli.cpp @@ -10,13 +10,13 @@ #include "chainparamsbase.h" #include "clientversion.h" +#include "fs.h" #include "rpc/client.h" #include "rpc/protocol.h" #include "stacktraces.h" #include "util.h" #include "utilstrencodings.h" -#include #include #include @@ -99,7 +99,7 @@ static int AppInitRPC(int argc, char* argv[]) return EXIT_SUCCESS; } bool datadirFromCmdLine = IsArgSet("-datadir"); - if (datadirFromCmdLine && !boost::filesystem::is_directory(GetDataDir(false))) { + if (datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str()); return EXIT_FAILURE; } diff --git a/src/dashd.cpp b/src/dashd.cpp index 048c4749597d..c67891d547b4 100644 --- a/src/dashd.cpp +++ b/src/dashd.cpp @@ -11,6 +11,7 @@ #include "chainparams.h" #include "clientversion.h" #include "compat.h" +#include "fs.h" #include "rpc/server.h" #include "init.h" #include "noui.h" @@ -22,7 +23,6 @@ #include "stacktraces.h" #include -#include #include #include @@ -100,7 +100,7 @@ bool AppInit(int argc, char* argv[]) try { bool datadirFromCmdLine = IsArgSet("-datadir"); - if (datadirFromCmdLine && !boost::filesystem::is_directory(GetDataDir(false))) + if (datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str()); return false; diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index aa5dc34d0884..2538ea0ce372 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -4,11 +4,10 @@ #include "dbwrapper.h" +#include "fs.h" #include "util.h" #include "random.h" -#include - #include #include #include @@ -91,7 +90,7 @@ static leveldb::Options GetOptions(size_t nCacheSize) return options; } -CDBWrapper::CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate) +CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bool fWipe, bool obfuscate) { penv = NULL; readoptions.verify_checksums = true; diff --git a/src/dbwrapper.h b/src/dbwrapper.h index d32c394d186b..f6970bc42421 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -6,6 +6,7 @@ #define BITCOIN_DBWRAPPER_H #include "clientversion.h" +#include "fs.h" #include "serialize.h" #include "streams.h" #include "util.h" @@ -240,7 +241,7 @@ class CDBWrapper * @param[in] obfuscate If true, store data obfuscated via simple XOR. If false, XOR * with a zero'd byte array. */ - CDBWrapper(const boost::filesystem::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false); + CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory = false, bool fWipe = false, bool obfuscate = false); ~CDBWrapper(); template diff --git a/src/fs.cpp b/src/fs.cpp new file mode 100644 index 000000000000..6f2b768de322 --- /dev/null +++ b/src/fs.cpp @@ -0,0 +1,17 @@ +#include "fs.h" + +#include + +namespace fsbridge { + +FILE *fopen(const fs::path& p, const char *mode) +{ + return ::fopen(p.string().c_str(), mode); +} + +FILE *freopen(const fs::path& p, const char *mode, FILE *stream) +{ + return ::freopen(p.string().c_str(), mode, stream); +} + +} // fsbridge diff --git a/src/fs.h b/src/fs.h new file mode 100644 index 000000000000..585cbf9c3825 --- /dev/null +++ b/src/fs.h @@ -0,0 +1,24 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_FS_H +#define BITCOIN_FS_H + +#include +#include + +#include +#include +#include + +/** Filesystem operations and types */ +namespace fs = boost::filesystem; + +/** Bridge operations to C stdio */ +namespace fsbridge { + FILE *fopen(const fs::path& p, const char *mode); + FILE *freopen(const fs::path& p, const char *mode, FILE *stream); +}; + +#endif diff --git a/src/init.cpp b/src/init.cpp index 292258d1133d..05acb8758968 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -18,6 +18,7 @@ #include "checkpoints.h" #include "compat/sanity.h" #include "consensus/validation.h" +#include "fs.h" #include "httpserver.h" #include "httprpc.h" #include "key.h" @@ -86,7 +87,6 @@ #include #include #include -#include #include #include #include @@ -284,8 +284,8 @@ void PrepareShutdown() if (fFeeEstimatesInitialized) { - boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; - CAutoFile est_fileout(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION); + fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; + CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, CLIENT_VERSION); if (!est_fileout.IsNull()) mempool.WriteFeeEstimates(est_fileout); else @@ -340,8 +340,8 @@ void PrepareShutdown() #ifndef WIN32 try { - boost::filesystem::remove(GetPidFile()); - } catch (const boost::filesystem::filesystem_error& e) { + fs::remove(GetPidFile()); + } catch (const fs::filesystem_error& e) { LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what()); } #endif @@ -723,14 +723,14 @@ struct CImportingNow // works correctly. void CleanupBlockRevFiles() { - std::map mapBlockFiles; + std::map mapBlockFiles; // Glob all blk?????.dat and rev?????.dat files from the blocks directory. // Remove the rev files immediately and insert the blk file paths into an // ordered map keyed by block file index. LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n"); - boost::filesystem::path blocksdir = GetDataDir() / "blocks"; - for (boost::filesystem::directory_iterator it(blocksdir); it != boost::filesystem::directory_iterator(); it++) { + fs::path blocksdir = GetDataDir() / "blocks"; + for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) { if (is_regular_file(*it) && it->path().filename().string().length() == 12 && it->path().filename().string().substr(8,4) == ".dat") @@ -747,7 +747,7 @@ void CleanupBlockRevFiles() // keeping a separate counter. Once we hit a gap (or if 0 doesn't exist) // start removing block files. int nContigCounter = 0; - BOOST_FOREACH(const PAIRTYPE(std::string, boost::filesystem::path)& item, mapBlockFiles) { + BOOST_FOREACH(const PAIRTYPE(std::string, fs::path)& item, mapBlockFiles) { if (atoi(item.first) == nContigCounter) { nContigCounter++; continue; @@ -756,7 +756,7 @@ void CleanupBlockRevFiles() } } -void ThreadImport(std::vector vImportFiles) +void ThreadImport(std::vector vImportFiles) { const CChainParams& chainparams = Params(); RenameThread("dash-loadblk"); @@ -769,7 +769,7 @@ void ThreadImport(std::vector vImportFiles) int nFile = 0; while (true) { CDiskBlockPos pos(nFile, 0); - if (!boost::filesystem::exists(GetBlockPosFilename(pos, "blk"))) + if (!fs::exists(GetBlockPosFilename(pos, "blk"))) break; // No block files left to reindex FILE *file = OpenBlockFile(pos, true); if (!file) @@ -786,11 +786,11 @@ void ThreadImport(std::vector vImportFiles) } // hardcoded $DATADIR/bootstrap.dat - boost::filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; - if (boost::filesystem::exists(pathBootstrap)) { - FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); + fs::path pathBootstrap = GetDataDir() / "bootstrap.dat"; + if (fs::exists(pathBootstrap)) { + FILE *file = fsbridge::fopen(pathBootstrap, "rb"); if (file) { - boost::filesystem::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; + fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; LogPrintf("Importing bootstrap.dat...\n"); LoadExternalBlockFile(chainparams, file); RenameOver(pathBootstrap, pathBootstrapOld); @@ -800,8 +800,8 @@ void ThreadImport(std::vector vImportFiles) } // -loadblock= - BOOST_FOREACH(const boost::filesystem::path& path, vImportFiles) { - FILE *file = fopen(path.string().c_str(), "rb"); + BOOST_FOREACH(const fs::path& path, vImportFiles) { + FILE *file = fsbridge::fopen(path, "rb"); if (file) { LogPrintf("Importing blocks file %s...\n", path.string()); LoadExternalBlockFile(chainparams, file); @@ -1439,8 +1439,8 @@ static bool LockDataDirectory(bool probeOnly) std::string strDataDir = GetDataDir().string(); // Make sure only a single Dash Core process is using the data directory. - boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; - FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. + fs::path pathLockFile = GetDataDir() / ".lock"; + FILE* file = fsbridge::fopen(pathLockFile, "a"); // empty lock file; created if it doesn't exist. if (file) fclose(file); try { @@ -1765,7 +1765,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) fReindex = GetBoolArg("-reindex", false); bool fReindexChainState = GetBoolArg("-reindex-chainstate", false); - boost::filesystem::create_directories(GetDataDir() / "blocks"); + fs::create_directories(GetDataDir() / "blocks"); // cache size calculations int64_t nTotalCache = (GetArg("-dbcache", nDefaultDbCache) << 20); @@ -1922,8 +1922,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); - boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; - CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); + fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; + CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION); // Allowed to fail as this file IS missing on first startup. if (!est_filein.IsNull()) mempool.ReadFeeEstimates(est_filein); @@ -2098,7 +2098,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) if (IsArgSet("-blocknotify")) uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); - std::vector vImportFiles; + std::vector vImportFiles; if (mapMultiArgs.count("-loadblock")) { BOOST_FOREACH(const std::string& strFile, mapMultiArgs.at("-loadblock")) diff --git a/src/net.h b/src/net.h index 48baf7a1045a..694ed56a1f85 100644 --- a/src/net.h +++ b/src/net.h @@ -10,6 +10,7 @@ #include "addrman.h" #include "bloom.h" #include "compat.h" +#include "fs.h" #include "hash.h" #include "limitedmap.h" #include "netaddress.h" @@ -35,7 +36,6 @@ #include #endif -#include #include #include diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp index 94a22ac21131..1f351bc839a2 100644 --- a/src/qt/dash.cpp +++ b/src/qt/dash.cpp @@ -11,6 +11,7 @@ #include "chainparams.h" #include "clientmodel.h" +#include "fs.h" #include "guiconstants.h" #include "guiutil.h" #include "intro.h" @@ -41,7 +42,6 @@ #include -#include #include #include @@ -646,7 +646,7 @@ int main(int argc, char *argv[]) /// 6. Determine availability of data directory and parse dash.conf /// - Do not call GetDataDir(true) before this step finishes - if (!boost::filesystem::is_directory(GetDataDir(false))) + if (!fs::is_directory(GetDataDir(false))) { QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(GetArg("-datadir", "")))); diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 422c0a76c970..1e75eb60f397 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -10,6 +10,7 @@ #include "qvalidatedlineedit.h" #include "walletmodel.h" +#include "fs.h" #include "primitives/transaction.h" #include "init.h" #include "policy/policy.h" @@ -36,9 +37,6 @@ #include "shlwapi.h" #endif -#include -#include -#include #include #include @@ -66,7 +64,7 @@ #include #endif -static boost::filesystem::detail::utf8_codecvt_facet utf8; +static fs::detail::utf8_codecvt_facet utf8; #if defined(Q_OS_MAC) extern double NSAppKitVersionNumber; @@ -166,7 +164,7 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) QUrlQuery uriQuery(uri); QList > items = uriQuery.queryItems(); #endif - + rv.fUseInstantSend = false; for (QList >::iterator i = items.begin(); i != items.end(); i++) { @@ -254,7 +252,7 @@ QString formatBitcoinURI(const SendCoinsRecipient &info) ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg); paramCount++; } - + if(info.fUseInstantSend) { ret += QString("%1IS=1").arg(paramCount == 0 ? "?" : "&"); @@ -427,10 +425,10 @@ bool isObscured(QWidget *w) void openDebugLogfile() { - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + fs::path pathDebug = GetDataDir() / "debug.log"; /* Open debug.log with the associated application */ - if (boost::filesystem::exists(pathDebug)) + if (fs::exists(pathDebug)) QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathDebug))); } @@ -635,7 +633,7 @@ TableViewLastColumnResizingFixer::TableViewLastColumnResizingFixer(QTableView* t } #ifdef WIN32 -boost::filesystem::path static StartupShortcutPath() +fs::path static StartupShortcutPath() { std::string chain = ChainNameFromCommandLine(); if (chain == CBaseChainParams::MAIN) @@ -648,13 +646,13 @@ boost::filesystem::path static StartupShortcutPath() bool GetStartOnSystemStartup() { // check for "Dash Core*.lnk" - return boost::filesystem::exists(StartupShortcutPath()); + return fs::exists(StartupShortcutPath()); } bool SetStartOnSystemStartup(bool fAutoStart) { // If the shortcut exists already, remove it for updating - boost::filesystem::remove(StartupShortcutPath()); + fs::remove(StartupShortcutPath()); if (fAutoStart) { @@ -724,10 +722,8 @@ bool SetStartOnSystemStartup(bool fAutoStart) // Follow the Desktop Application Autostart Spec: // http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html -boost::filesystem::path static GetAutostartDir() +fs::path static GetAutostartDir() { - namespace fs = boost::filesystem; - char* pszConfigHome = getenv("XDG_CONFIG_HOME"); if (pszConfigHome) return fs::path(pszConfigHome) / "autostart"; char* pszHome = getenv("HOME"); @@ -735,7 +731,7 @@ boost::filesystem::path static GetAutostartDir() return fs::path(); } -boost::filesystem::path static GetAutostartFilePath() +fs::path static GetAutostartFilePath() { std::string chain = ChainNameFromCommandLine(); if (chain == CBaseChainParams::MAIN) @@ -745,7 +741,7 @@ boost::filesystem::path static GetAutostartFilePath() bool GetStartOnSystemStartup() { - boost::filesystem::ifstream optionFile(GetAutostartFilePath()); + fs::ifstream optionFile(GetAutostartFilePath()); if (!optionFile.good()) return false; // Scan through file for "Hidden=true": @@ -765,7 +761,7 @@ bool GetStartOnSystemStartup() bool SetStartOnSystemStartup(bool fAutoStart) { if (!fAutoStart) - boost::filesystem::remove(GetAutostartFilePath()); + fs::remove(GetAutostartFilePath()); else { char pszExePath[MAX_PATH+1]; @@ -773,9 +769,9 @@ bool SetStartOnSystemStartup(bool fAutoStart) if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1) return false; - boost::filesystem::create_directories(GetAutostartDir()); + fs::create_directories(GetAutostartDir()); - boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc); + fs::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc); if (!optionFile.good()) return false; std::string chain = ChainNameFromCommandLine(); @@ -915,7 +911,7 @@ QString getThemeName() if(!theme.isEmpty()){ return theme; } - return QString("light"); + return QString("light"); } // Open CSS when configured @@ -927,18 +923,18 @@ QString loadStyleSheet() QString theme = settings.value("theme", "").toString(); if(!theme.isEmpty()){ - cssName = QString(":/css/") + theme; + cssName = QString(":/css/") + theme; } else { - cssName = QString(":/css/light"); + cssName = QString(":/css/light"); settings.setValue("theme", "light"); } - - QFile qFile(cssName); + + QFile qFile(cssName); if (qFile.open(QFile::ReadOnly)) { styleSheet = QLatin1String(qFile.readAll()); } - + return styleSheet; } @@ -948,12 +944,12 @@ void setClipboard(const QString& str) QApplication::clipboard()->setText(str, QClipboard::Selection); } -boost::filesystem::path qstringToBoostPath(const QString &path) +fs::path qstringToBoostPath(const QString &path) { - return boost::filesystem::path(path.toStdString(), utf8); + return fs::path(path.toStdString(), utf8); } -QString boostPathToQString(const boost::filesystem::path &path) +QString boostPathToQString(const fs::path &path) { return QString::fromStdString(path.string(utf8)); } diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 9360d8e85fb3..3865b8c2358d 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -6,6 +6,7 @@ #define BITCOIN_QT_GUIUTIL_H #include "amount.h" +#include "fs.h" #include #include @@ -16,8 +17,6 @@ #include #include -#include - class QValidatedLineEdit; class SendCoinsRecipient; @@ -198,10 +197,10 @@ namespace GUIUtil QString getThemeName(); /* Convert QString to OS specific boost path through UTF-8 */ - boost::filesystem::path qstringToBoostPath(const QString &path); + fs::path qstringToBoostPath(const QString &path); /* Convert OS specific boost path to QString through UTF-8 */ - QString boostPathToQString(const boost::filesystem::path &path); + QString boostPathToQString(const fs::path &path); /* Convert seconds into a QString with days, hours, mins, secs */ QString formatDurationStr(int secs); diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 163fd71d733f..bc8bce7a791c 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -7,6 +7,7 @@ #include "config/dash-config.h" #endif +#include "fs.h" #include "intro.h" #include "ui_intro.h" @@ -14,8 +15,6 @@ #include "util.h" -#include - #include #include #include @@ -71,7 +70,6 @@ FreespaceChecker::FreespaceChecker(Intro *_intro) void FreespaceChecker::check() { - namespace fs = boost::filesystem; QString dataDirStr = intro->getPathToCheck(); fs::path dataDir = GUIUtil::qstringToBoostPath(dataDirStr); uint64_t freeBytesAvailable = 0; @@ -191,7 +189,6 @@ QString Intro::getDefaultDataDirectory() bool Intro::pickDataDirectory() { - namespace fs = boost::filesystem; QSettings settings; /* If data directory provided on command line, no need to look at settings or show a picking dialog */ diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index cacfa5f69de6..239949626d96 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -6,6 +6,7 @@ #include "chainparams.h" #include "consensus/validation.h" +#include "fs.h" #include "validation.h" #include "rpc/register.h" #include "rpc/server.h" @@ -20,8 +21,6 @@ #include #include -#include - static UniValue rpcNestedTest_rpc(const JSONRPCRequest& request) { if (request.fHelp) { @@ -168,5 +167,5 @@ void RPCNestedTests::rpcNestedTests() delete evoDb; evoDb = nullptr; - boost::filesystem::remove_all(boost::filesystem::path(path)); + fs::remove_all(fs::path(path)); } diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 25e5e4b209b7..a20fa89ad08a 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -67,9 +67,9 @@ static const std::string COOKIEAUTH_USER = "__cookie__"; /** Default name for auth cookie file */ static const std::string COOKIEAUTH_FILE = ".cookie"; -boost::filesystem::path GetAuthCookieFile() +fs::path GetAuthCookieFile() { - boost::filesystem::path path(GetArg("-rpccookiefile", COOKIEAUTH_FILE)); + fs::path path(GetArg("-rpccookiefile", COOKIEAUTH_FILE)); if (!path.is_complete()) path = GetDataDir() / path; return path; } @@ -86,7 +86,7 @@ bool GenerateAuthCookie(std::string *cookie_out) * these are set to 077 in init.cpp unless overridden with -sysperms. */ std::ofstream file; - boost::filesystem::path filepath = GetAuthCookieFile(); + fs::path filepath = GetAuthCookieFile(); file.open(filepath.string().c_str()); if (!file.is_open()) { LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath.string()); @@ -105,7 +105,7 @@ bool GetAuthCookie(std::string *cookie_out) { std::ifstream file; std::string cookie; - boost::filesystem::path filepath = GetAuthCookieFile(); + fs::path filepath = GetAuthCookieFile(); file.open(filepath.string().c_str()); if (!file.is_open()) return false; @@ -120,8 +120,8 @@ bool GetAuthCookie(std::string *cookie_out) void DeleteAuthCookie() { try { - boost::filesystem::remove(GetAuthCookieFile()); - } catch (const boost::filesystem::filesystem_error& e) { + fs::remove(GetAuthCookieFile()); + } catch (const fs::filesystem_error& e) { LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, e.what()); } } diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h index f10a0e281301..54c14206e43e 100644 --- a/src/rpc/protocol.h +++ b/src/rpc/protocol.h @@ -6,11 +6,12 @@ #ifndef BITCOIN_RPCPROTOCOL_H #define BITCOIN_RPCPROTOCOL_H +#include "fs.h" + #include #include #include #include -#include #include @@ -89,7 +90,7 @@ std::string JSONRPCReply(const UniValue& result, const UniValue& error, const Un UniValue JSONRPCError(int code, const std::string& message); /** Get name of RPC authentication cookie file */ -boost::filesystem::path GetAuthCookieFile(); +fs::path GetAuthCookieFile(); /** Generate a new RPC authentication cookie and write it to disk */ bool GenerateAuthCookie(std::string *cookie_out); /** Read the RPC authentication cookie from disk */ diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index d437fb929dd9..1df9304bc015 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -7,6 +7,7 @@ #include "rpc/server.h" #include "base58.h" +#include "fs.h" #include "init.h" #include "random.h" #include "sync.h" @@ -17,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 371d103c7d35..ae470b48e964 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper) // Perform tests both obfuscated and non-obfuscated. for (int i = 0; i < 2; i++) { bool obfuscate = (bool)i; - boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'k'; uint256 in = GetRandHash(); @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) // Perform tests both obfuscated and non-obfuscated. for (int i = 0; i < 2; i++) { bool obfuscate = (bool)i; - boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'i'; @@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) // Perform tests both obfuscated and non-obfuscated. for (int i = 0; i < 2; i++) { bool obfuscate = (bool)i; - boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); // The two keys are intentionally chosen for ordering @@ -125,8 +125,8 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) // Test that we do not obfuscation if there is existing data. BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) { - // We're going to share this boost::filesystem::path between two wrappers - boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + // We're going to share this fs::path between two wrappers + fs::path ph = fs::temp_directory_path() / fs::unique_path(); create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. @@ -167,8 +167,8 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) // Ensure that we start obfuscating during a reindex. BOOST_AUTO_TEST_CASE(existing_data_reindex) { - // We're going to share this boost::filesystem::path between two wrappers - boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + // We're going to share this fs::path between two wrappers + fs::path ph = fs::temp_directory_path() / fs::unique_path(); create_directories(ph); // Set up a non-obfuscated wrapper to write some initial data. @@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_AUTO_TEST_CASE(iterator_ordering) { - boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, false); for (int x=0x00; x<256; ++x) { uint8_t key = x; @@ -275,7 +275,7 @@ BOOST_AUTO_TEST_CASE(iterator_string_ordering) { char buf[10]; - boost::filesystem::path ph = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path(); + fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, false); for (int x=0x00; x<10; ++x) { for (int y = 0; y < 10; y++) { diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index 73b96f55fcff..19f4e0faeb6a 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -7,6 +7,7 @@ #include "chainparams.h" #include "consensus/consensus.h" #include "consensus/validation.h" +#include "fs.h" #include "key.h" #include "validation.h" #include "miner.h" @@ -29,7 +30,6 @@ #include -#include #include FastRandomContext insecure_rand_ctx(true); @@ -69,7 +69,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha RegisterAllCoreRPCCommands(tableRPC); ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_dash_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); - boost::filesystem::create_directories(pathTemp); + fs::create_directories(pathTemp); ForceSetArg("-datadir", pathTemp.string()); mempool.setSanityCheck(1.0); g_connman = std::unique_ptr(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests. @@ -104,7 +104,7 @@ TestingSetup::~TestingSetup() llmq::DestroyLLMQSystem(); delete pcoinsdbview; delete pblocktree; - boost::filesystem::remove_all(pathTemp); + fs::remove_all(pathTemp); } TestChainSetup::TestChainSetup(int blockCount) : TestingSetup(CBaseChainParams::REGTEST) diff --git a/src/test/test_dash.h b/src/test/test_dash.h index f9ca803f1879..480c0647031d 100644 --- a/src/test/test_dash.h +++ b/src/test/test_dash.h @@ -7,12 +7,12 @@ #define BITCOIN_TEST_TEST_DASH_H #include "chainparamsbase.h" +#include "fs.h" #include "key.h" #include "pubkey.h" #include "txdb.h" #include "txmempool.h" -#include #include /** Basic testing setup. @@ -31,7 +31,7 @@ struct BasicTestingSetup { class CConnman; struct TestingSetup: public BasicTestingSetup { CCoinsViewDB *pcoinsdbview; - boost::filesystem::path pathTemp; + fs::path pathTemp; boost::thread_group threadGroup; CConnman* connman; diff --git a/src/test/testutil.cpp b/src/test/testutil.cpp index e6d86229796b..591d0bf30271 100644 --- a/src/test/testutil.cpp +++ b/src/test/testutil.cpp @@ -8,8 +8,8 @@ #include #endif -#include +#include "fs.h" -boost::filesystem::path GetTempPath() { - return boost::filesystem::temp_directory_path(); +fs::path GetTempPath() { + return fs::temp_directory_path(); } diff --git a/src/test/testutil.h b/src/test/testutil.h index 5875dc50e6c7..cbe784d6400b 100644 --- a/src/test/testutil.h +++ b/src/test/testutil.h @@ -8,8 +8,8 @@ #ifndef BITCOIN_TEST_TESTUTIL_H #define BITCOIN_TEST_TESTUTIL_H -#include +#include "fs.h" -boost::filesystem::path GetTempPath(); +fs::path GetTempPath(); #endif // BITCOIN_TEST_TESTUTIL_H diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 2ab6a558ee35..91e087bdfc61 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -314,9 +314,9 @@ static std::map ParseTorReplyMapping(const std::string * @param maxsize Puts a maximum size limit on the file that is read. If the file is larger than this, truncated data * (with len > maxsize) will be returned. */ -static std::pair ReadBinaryFile(const std::string &filename, size_t maxsize=std::numeric_limits::max()) +static std::pair ReadBinaryFile(const fs::path &filename, size_t maxsize=std::numeric_limits::max()) { - FILE *f = fopen(filename.c_str(), "rb"); + FILE *f = fsbridge::fopen(filename, "rb"); if (f == NULL) return std::make_pair(false,""); std::string retval; @@ -334,9 +334,9 @@ static std::pair ReadBinaryFile(const std::string &filename, s /** Write contents of std::string to a file. * @return true on success. */ -static bool WriteBinaryFile(const std::string &filename, const std::string &data) +static bool WriteBinaryFile(const fs::path &filename, const std::string &data) { - FILE *f = fopen(filename.c_str(), "wb"); + FILE *f = fsbridge::fopen(filename, "wb"); if (f == NULL) return false; if (fwrite(data.data(), 1, data.size(), f) != data.size()) { @@ -359,7 +359,7 @@ class TorController ~TorController(); /** Get name fo file to store private key in */ - std::string GetPrivateKeyFile(); + fs::path GetPrivateKeyFile(); /** Reconnect, after getting disconnected */ void Reconnect(); @@ -411,7 +411,7 @@ TorController::TorController(struct event_base* _base, const std::string& _targe // Read service private key if cached std::pair pkf = ReadBinaryFile(GetPrivateKeyFile()); if (pkf.first) { - LogPrint(BCLog::TOR, "tor: Reading cached private key from %s\n", GetPrivateKeyFile()); + LogPrint(BCLog::TOR, "tor: Reading cached private key from %s\n", GetPrivateKeyFile().string()); private_key = pkf.second; } } @@ -442,9 +442,9 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe service = LookupNumeric(std::string(service_id+".onion").c_str(), GetListenPort()); LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString()); if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { - LogPrint(BCLog::TOR, "tor: Cached service private key to %s\n", GetPrivateKeyFile()); + LogPrint(BCLog::TOR, "tor: Cached service private key to %s\n", GetPrivateKeyFile().string()); } else { - LogPrintf("tor: Error writing service private key to %s\n", GetPrivateKeyFile()); + LogPrintf("tor: Error writing service private key to %s\n", GetPrivateKeyFile().string()); } AddLocal(service, LOCAL_MANUAL); // ... onion requested - keep connection open @@ -651,9 +651,9 @@ void TorController::Reconnect() } } -std::string TorController::GetPrivateKeyFile() +fs::path TorController::GetPrivateKeyFile() { - return (GetDataDir() / "onion_private_key").string(); + return GetDataDir() / "onion_private_key"; } void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg) diff --git a/src/util.cpp b/src/util.cpp index 5934b141c987..360322a8c308 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -13,6 +13,7 @@ #include "support/allocators/secure.h" #include "chainparamsbase.h" #include "ctpl.h" +#include "fs.h" #include "random.h" #include "serialize.h" #include "stacktraces.h" @@ -86,8 +87,6 @@ #include // for startswith() and endswith() #include #include -#include -#include #include #include #include @@ -235,8 +234,8 @@ void OpenDebugLog() assert(fileout == NULL); assert(vMsgsBeforeOpenLog); - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; - fileout = fopen(pathDebug.string().c_str(), "a"); + fs::path pathDebug = GetDataDir() / "debug.log"; + fileout = fsbridge::fopen(pathDebug, "a"); if (fileout) { setbuf(fileout, NULL); // unbuffered // dump buffered messages from before we opened the log @@ -451,8 +450,8 @@ int LogPrintStr(const std::string &str) // reopen the log file, if requested if (fReopenDebugLog) { fReopenDebugLog = false; - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; - if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) + fs::path pathDebug = GetDataDir() / "debug.log"; + if (fsbridge::freopen(pathDebug,"a",fileout) != NULL) setbuf(fileout, NULL); // unbuffered } @@ -609,9 +608,8 @@ void PrintExceptionContinue(const std::exception_ptr pex, const char* pszThread) fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); } -boost::filesystem::path GetDefaultDataDir() +fs::path GetDefaultDataDir() { - namespace fs = boost::filesystem; // Windows < Vista: C:\Documents and Settings\Username\Application Data\DashCore // Windows >= Vista: C:\Users\Username\AppData\Roaming\DashCore // Mac: ~/Library/Application Support/DashCore @@ -636,13 +634,12 @@ boost::filesystem::path GetDefaultDataDir() #endif } -static boost::filesystem::path pathCached; -static boost::filesystem::path pathCachedNetSpecific; +static fs::path pathCached; +static fs::path pathCachedNetSpecific; static CCriticalSection csPathCached; -const boost::filesystem::path &GetDataDir(bool fNetSpecific) +const fs::path &GetDataDir(bool fNetSpecific) { - namespace fs = boost::filesystem; LOCK(csPathCached); @@ -684,13 +681,13 @@ void ClearDatadirCache() { LOCK(csPathCached); - pathCached = boost::filesystem::path(); - pathCachedNetSpecific = boost::filesystem::path(); + pathCached = fs::path(); + pathCachedNetSpecific = fs::path(); } -boost::filesystem::path GetConfigFile(const std::string& confPath) +fs::path GetConfigFile(const std::string& confPath) { - boost::filesystem::path pathConfigFile(confPath); + fs::path pathConfigFile(confPath); if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile; @@ -699,7 +696,7 @@ boost::filesystem::path GetConfigFile(const std::string& confPath) void ReadConfigFile(const std::string& confPath) { - boost::filesystem::ifstream streamConfig(GetConfigFile(confPath)); + fs::ifstream streamConfig(GetConfigFile(confPath)); if (!streamConfig.good()){ // Create empty dash.conf if it does not excist FILE* configFile = fopen(GetConfigFile(confPath).string().c_str(), "a"); @@ -729,16 +726,16 @@ void ReadConfigFile(const std::string& confPath) } #ifndef WIN32 -boost::filesystem::path GetPidFile() +fs::path GetPidFile() { - boost::filesystem::path pathPidFile(GetArg("-pid", BITCOIN_PID_FILENAME)); + fs::path pathPidFile(GetArg("-pid", BITCOIN_PID_FILENAME)); if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile; return pathPidFile; } -void CreatePidFile(const boost::filesystem::path &path, pid_t pid) +void CreatePidFile(const fs::path &path, pid_t pid) { - FILE* file = fopen(path.string().c_str(), "w"); + FILE* file = fsbridge::fopen(path, "w"); if (file) { fprintf(file, "%d\n", pid); @@ -747,7 +744,7 @@ void CreatePidFile(const boost::filesystem::path &path, pid_t pid) } #endif -bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) +bool RenameOver(fs::path src, fs::path dest) { #ifdef WIN32 return MoveFileExA(src.string().c_str(), dest.string().c_str(), @@ -763,13 +760,13 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) * Specifically handles case where path p exists, but it wasn't possible for the user to * write to the parent directory. */ -bool TryCreateDirectory(const boost::filesystem::path& p) +bool TryCreateDirectory(const fs::path& p) { try { - return boost::filesystem::create_directory(p); - } catch (const boost::filesystem::filesystem_error&) { - if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p)) + return fs::create_directory(p); + } catch (const fs::filesystem_error&) { + if (!fs::exists(p) || !fs::is_directory(p)) throw; } @@ -876,11 +873,11 @@ void ShrinkDebugFile() // Amount of debug.log to save at end when shrinking (must fit in memory) constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000; // Scroll debug.log if it's getting too big - boost::filesystem::path pathLog = GetDataDir() / "debug.log"; - FILE* file = fopen(pathLog.string().c_str(), "r"); + fs::path pathLog = GetDataDir() / "debug.log"; + FILE* file = fsbridge::fopen(pathLog, "r"); // If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE // trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes - if (file && boost::filesystem::file_size(pathLog) > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10)) + if (file && fs::file_size(pathLog) > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10)) { // Restart the file with some of the end std::vector vch(RECENT_DEBUG_HISTORY_SIZE, 0); @@ -888,7 +885,7 @@ void ShrinkDebugFile() int nBytes = fread(vch.data(), 1, vch.size(), file); fclose(file); - file = fopen(pathLog.string().c_str(), "w"); + file = fsbridge::fopen(pathLog, "w"); if (file) { fwrite(vch.data(), 1, nBytes, file); @@ -900,10 +897,8 @@ void ShrinkDebugFile() } #ifdef WIN32 -boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate) +fs::path GetSpecialFolderPath(int nFolder, bool fCreate) { - namespace fs = boost::filesystem; - char pszPath[MAX_PATH] = ""; if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate)) @@ -1017,9 +1012,9 @@ void SetupEnvironment() // The path locale is lazy initialized and to avoid deinitialization errors // in multithreading environments, it is set explicitly by the main thread. // A dummy locale is used to extract the internal default locale, used by - // boost::filesystem::path, which is then used to explicitly imbue the path. - std::locale loc = boost::filesystem::path::imbue(std::locale::classic()); - boost::filesystem::path::imbue(loc); + // fs::path, which is then used to explicitly imbue the path. + std::locale loc = fs::path::imbue(std::locale::classic()); + fs::path::imbue(loc); } bool SetupNetworking() diff --git a/src/util.h b/src/util.h index 0af05ebe35d4..511ca00d1e8b 100644 --- a/src/util.h +++ b/src/util.h @@ -16,6 +16,7 @@ #endif #include "compat.h" +#include "fs.h" #include "tinyformat.h" #include "utiltime.h" #include "amount.h" @@ -28,7 +29,6 @@ #include #include -#include #include #include @@ -197,20 +197,20 @@ void FileCommit(FILE *file); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); -bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest); -bool TryCreateDirectory(const boost::filesystem::path& p); -boost::filesystem::path GetDefaultDataDir(); -const boost::filesystem::path &GetDataDir(bool fNetSpecific = true); +bool RenameOver(fs::path src, fs::path dest); +bool TryCreateDirectory(const fs::path& p); +fs::path GetDefaultDataDir(); +const fs::path &GetDataDir(bool fNetSpecific = true); boost::filesystem::path GetBackupsDir(); void ClearDatadirCache(); -boost::filesystem::path GetConfigFile(const std::string& confPath); +fs::path GetConfigFile(const std::string& confPath); #ifndef WIN32 -boost::filesystem::path GetPidFile(); -void CreatePidFile(const boost::filesystem::path &path, pid_t pid); +fs::path GetPidFile(); +void CreatePidFile(const fs::path &path, pid_t pid); #endif void ReadConfigFile(const std::string& confPath); #ifdef WIN32 -boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); +fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif void OpenDebugLog(); void ShrinkDebugFile(); diff --git a/src/validation.cpp b/src/validation.cpp index bd5fea3ffcd1..aaa67a55a712 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -15,6 +15,7 @@ #include "consensus/consensus.h" #include "consensus/merkle.h" #include "consensus/validation.h" +#include "fs.h" #include "hash.h" #include "init.h" #include "policy/policy.h" @@ -54,8 +55,6 @@ #include #include -#include -#include #include #include @@ -3732,8 +3731,8 @@ void UnlinkPrunedFiles(const std::set& setFilesToPrune) { for (std::set::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) { CDiskBlockPos pos(*it, 0); - boost::filesystem::remove(GetBlockPosFilename(pos, "blk")); - boost::filesystem::remove(GetBlockPosFilename(pos, "rev")); + fs::remove(GetBlockPosFilename(pos, "blk")); + fs::remove(GetBlockPosFilename(pos, "rev")); LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, *it); } } @@ -3817,7 +3816,7 @@ void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight bool CheckDiskSpace(uint64_t nAdditionalBytes) { - uint64_t nFreeBytesAvailable = boost::filesystem::space(GetDataDir()).available; + uint64_t nFreeBytesAvailable = fs::space(GetDataDir()).available; // Check for nMinDiskSpace bytes (currently 50MB) if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) @@ -3830,11 +3829,11 @@ FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) { if (pos.IsNull()) return NULL; - boost::filesystem::path path = GetBlockPosFilename(pos, prefix); - boost::filesystem::create_directories(path.parent_path()); - FILE* file = fopen(path.string().c_str(), "rb+"); + fs::path path = GetBlockPosFilename(pos, prefix); + fs::create_directories(path.parent_path()); + FILE* file = fsbridge::fopen(path, "rb+"); if (!file && !fReadOnly) - file = fopen(path.string().c_str(), "wb+"); + file = fsbridge::fopen(path, "wb+"); if (!file) { LogPrintf("Unable to open file %s\n", path.string()); return NULL; @@ -3857,7 +3856,7 @@ FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "rev", fReadOnly); } -boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix) +fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix) { return GetDataDir() / "blocks" / strprintf("%s%05u.dat", prefix, pos.nFile); } @@ -4554,7 +4553,7 @@ bool LoadMempool(void) } int64_t nExpiryTimeout = GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; - FILE* filestr = fopen((GetDataDir() / "mempool.dat").string().c_str(), "rb"); + FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb"); CAutoFile file(filestr, SER_DISK, CLIENT_VERSION); if (file.IsNull()) { LogPrintf("Failed to open mempool file from disk. Continuing anyway.\n"); @@ -4634,7 +4633,7 @@ void DumpMempool(void) int64_t mid = GetTimeMicros(); try { - FILE* filestr = fopen((GetDataDir() / "mempool.dat.new").string().c_str(), "wb"); + FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat.new", "wb"); if (!filestr) { return; } diff --git a/src/validation.h b/src/validation.h index 3f7aca5fc806..cc4910827f04 100644 --- a/src/validation.h +++ b/src/validation.h @@ -14,6 +14,7 @@ #include "amount.h" #include "chain.h" #include "coins.h" +#include "fs.h" #include "protocol.h" // For CMessageHeader::MessageStartChars #include "script/script_error.h" #include "sync.h" @@ -32,7 +33,6 @@ #include #include -#include class CBlockIndex; class CBlockTreeDB; @@ -260,7 +260,7 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Open an undo file (rev?????.dat) */ FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ -boost::filesystem::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); +fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); /** Import blocks from an external file */ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskBlockPos *dbp = NULL); /** Initialize a new block tree database + block data on disk */ diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 5d0d50b6de5c..f0a5be2a66cc 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -6,6 +6,7 @@ #include "db.h" #include "addrman.h" +#include "fs.h" #include "hash.h" #include "protocol.h" #include "util.h" @@ -17,7 +18,6 @@ #include #endif -#include #include #include #include @@ -66,7 +66,7 @@ void CDBEnv::Close() EnvShutdown(); } -bool CDBEnv::Open(const boost::filesystem::path& pathIn) +bool CDBEnv::Open(const fs::path& pathIn) { if (fDbEnvInit) return true; @@ -74,9 +74,9 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) boost::this_thread::interruption_point(); strPath = pathIn.string(); - boost::filesystem::path pathLogDir = pathIn / "database"; + fs::path pathLogDir = pathIn / "database"; TryCreateDirectory(pathLogDir); - boost::filesystem::path pathErrorFile = pathIn / "db.log"; + fs::path pathErrorFile = pathIn / "db.log"; LogPrintf("CDBEnv::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string()); unsigned int nEnvFlags = 0; @@ -89,7 +89,7 @@ bool CDBEnv::Open(const boost::filesystem::path& pathIn) dbenv->set_lg_max(1048576); dbenv->set_lk_max_locks(40000); dbenv->set_lk_max_objects(40000); - dbenv->set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug + dbenv->set_errfile(fsbridge::fopen(pathErrorFile, "a")); /// debug dbenv->set_flags(DB_AUTO_COMMIT, 1); dbenv->set_flags(DB_TXN_WRITE_NOSYNC, 1); dbenv->log_set_config(DB_LOG_AUTO_REMOVE, 1); @@ -226,13 +226,13 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco return fSuccess; } -bool CDB::VerifyEnvironment(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& errorStr) +bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr) { LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); LogPrintf("Using wallet %s\n", walletFile); // Wallet file must be a plain filename without a directory - if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile)) + if (walletFile != fs::basename(walletFile) + fs::extension(walletFile)) { errorStr = strprintf(_("Wallet %s resides outside data directory %s"), walletFile, dataDir.string()); return false; @@ -241,12 +241,12 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const boost::filesyst if (!bitdb.Open(dataDir)) { // try moving the database env out of the way - boost::filesystem::path pathDatabase = dataDir / "database"; - boost::filesystem::path pathDatabaseBak = dataDir / strprintf("database.%d.bak", GetTime()); + fs::path pathDatabase = dataDir / "database"; + fs::path pathDatabaseBak = dataDir / strprintf("database.%d.bak", GetTime()); try { - boost::filesystem::rename(pathDatabase, pathDatabaseBak); + fs::rename(pathDatabase, pathDatabaseBak); LogPrintf("Moved old %s to %s. Retrying.\n", pathDatabase.string(), pathDatabaseBak.string()); - } catch (const boost::filesystem::filesystem_error&) { + } catch (const fs::filesystem_error&) { // failure is ok (well, not really, but it's not worse than what we started with) } @@ -260,9 +260,9 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const boost::filesyst return true; } -bool CDB::VerifyDatabaseFile(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)) +bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)) { - if (boost::filesystem::exists(dataDir / walletFile)) + if (fs::exists(dataDir / walletFile)) { CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc); if (r == CDBEnv::RECOVER_OK) @@ -589,7 +589,7 @@ void CDBEnv::Flush(bool fShutdown) dbenv->log_archive(&listp, DB_ARCH_REMOVE); Close(); if (!fMockDb) - boost::filesystem::remove_all(boost::filesystem::path(strPath) / "database"); + fs::remove_all(fs::path(strPath) / "database"); } } } diff --git a/src/wallet/db.h b/src/wallet/db.h index 541a922ac4b5..d390574f49c7 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -7,6 +7,7 @@ #define BITCOIN_WALLET_DB_H #include "clientversion.h" +#include "fs.h" #include "serialize.h" #include "streams.h" #include "sync.h" @@ -16,8 +17,6 @@ #include #include -#include - #include static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100; @@ -28,7 +27,7 @@ class CDBEnv private: bool fDbEnvInit; bool fMockDb; - // Don't change into boost::filesystem::path, as that can result in + // Don't change into fs::path, as that can result in // shutdown problems/crashes caused by a static initialized internal pointer. std::string strPath; @@ -67,7 +66,7 @@ class CDBEnv typedef std::pair, std::vector > KeyValPair; bool Salvage(const std::string& strFile, bool fAggressive, std::vector& vResult); - bool Open(const boost::filesystem::path& path); + bool Open(const fs::path& path); void Close(); void Flush(bool fShutdown); void CheckpointLSN(const std::string& strFile); @@ -110,9 +109,9 @@ class CDB ideal to be called periodically */ static bool PeriodicFlush(std::string strFile); /* verifies the database environment */ - static bool VerifyEnvironment(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& errorStr); + static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)); private: CDB(const CDB&); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index ea8d78f94c88..da101d91612b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -12,6 +12,7 @@ #include "wallet/coincontrol.h" #include "consensus/consensus.h" #include "consensus/validation.h" +#include "fs.h" #include "key.h" #include "keystore.h" #include "validation.h" @@ -42,7 +43,6 @@ #include #include -#include #include CWallet* pwalletMain = NULL; @@ -5172,16 +5172,16 @@ bool CWallet::BackupWallet(const std::string& strDest) bitdb.mapFileUseCount.erase(strWalletFile); // Copy wallet file - boost::filesystem::path pathSrc = GetDataDir() / strWalletFile; - boost::filesystem::path pathDest(strDest); - if (boost::filesystem::is_directory(pathDest)) + fs::path pathSrc = GetDataDir() / strWalletFile; + fs::path pathDest(strDest); + if (fs::is_directory(pathDest)) pathDest /= strWalletFile; try { - boost::filesystem::copy_file(pathSrc, pathDest, boost::filesystem::copy_option::overwrite_if_exists); + fs::copy_file(pathSrc, pathDest, fs::copy_option::overwrite_if_exists); LogPrintf("copied %s to %s\n", strWalletFile, pathDest.string()); return true; - } catch (const boost::filesystem::filesystem_error& e) { + } catch (const fs::filesystem_error& e) { LogPrintf("error copying %s to %s - %s\n", strWalletFile, pathDest.string(), e.what()); return false; } diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index d13d3d5faa73..6c94ea566a26 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -8,6 +8,7 @@ #include "base58.h" #include "consensus/validation.h" +#include "fs.h" #include "validation.h" // For CheckTransaction #include "protocol.h" #include "serialize.h" @@ -18,7 +19,6 @@ #include -#include #include #include @@ -875,12 +875,12 @@ bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDa return true; } -bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& errorStr) +bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr) { return CDB::VerifyEnvironment(walletFile, dataDir, errorStr); } -bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& warningStr, std::string& errorStr) +bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr) { return CDB::VerifyDatabaseFile(walletFile, dataDir, errorStr, warningStr, CWalletDB::Recover); } diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index cad8a2cdb49b..c333c36a0d1e 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -140,9 +140,9 @@ class CWalletDB : public CDB /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ static bool IsKeyType(const std::string& strType); /* verifies the database environment */ - static bool VerifyEnvironment(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& errorStr); + static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const boost::filesystem::path& dataDir, std::string& warningStr, std::string& errorStr); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr); //! write the hdchain model (external chain child index counter) bool WriteHDChain(const CHDChain& chain); From f893ac66ca845ba641557959b201acb40ca40eda Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 8 Apr 2017 12:33:14 +0200 Subject: [PATCH 099/987] Merge #10124: [test] Suppress test logging spam 45ce471 Reduce spammy test logging (John Newbery) Tree-SHA512: 64b2ce29fb62a4e738840bbaf93563559451c2ef078ba66ecfc1dbe34adefea61ad2ad2d768444cb2e0b30cb3cbe47e38ed818d4c91f7723a3d1ba9fdd0043f9 --- test/functional/test_framework/mininode.py | 14 ++++++++++++-- test/functional/test_framework/util.py | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index e57af5b5597c..b80bca2a0d8a 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -1886,7 +1886,7 @@ def got_data(self): def send_message(self, message, pushbuf=False): if self.state != "connected" and not pushbuf: raise IOError('Not connected, no pushbuf') - logger.debug("Send message to %s:%d: %s" % (self.dstaddr, self.dstport, repr(message))) + self._log_message("send", message) command = message.command data = message.serialize() tmsg = self.MAGIC_BYTES[self.network] @@ -1908,9 +1908,19 @@ def got_message(self, message): self.messagemap[b'ping'] = msg_ping_prebip31 if self.last_sent + 30 * 60 < time.time(): self.send_message(self.messagemap[b'ping']()) - logger.debug("Received message from %s:%d: %s" % (self.dstaddr, self.dstport, repr(message))) + self._log_message("receive", message) self.cb.deliver(self, message) + def _log_message(self, direction, msg): + if direction == "send": + log_message = "Send message to " + elif direction == "receive": + log_message = "Received message from " + log_message += "%s:%d: %s" % (self.dstaddr, self.dstport, repr(msg)[:500]) + if len(log_message) > 500: + log_message += "... (msg truncated)" + logger.debug(log_message) + def disconnect_node(self): self.disconnect = True diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 2b8f6cdd26ae..2264184e2a3c 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -343,7 +343,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= if binary is None: binary = os.getenv("BITCOIND", "dashd") # RPC tests still depend on free transactions - args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000", "-logtimemicros", "-debug", "-mocktime="+str(get_mocktime()) ] + args = [binary, "-datadir=" + datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(get_mocktime())] # Don't try auto backups (they fail a lot when running tests) args += [ "-createwalletbackups=0" ] if extra_args is not None: args.extend(extra_args) From 60438257a5288a2f3e40b819b21e05dfa3101b9d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 10 Apr 2017 21:06:42 +0200 Subject: [PATCH 100/987] Merge #9725: CValidationInterface Cleanups b1a6d4c Take a CTransactionRef in AddToWalletIfInvolvingMe to avoid a copy (Matt Corallo) 1c95e2f Use std::shared_ptr instead of boost::shared_ptr in ScriptForMining (Matt Corallo) 91f1e6c Remove dead-code tracking of requests for blocks we generated (Matt Corallo) acad82f Add override to functions using CValidationInterface methods (Matt Corallo) e6d5e6c Hold cs_wallet for whole block [dis]connection processing (Matt Corallo) 461e49f SyncTransaction->TxAddedToMempool/BlockConnected/Disconnected (Matt Corallo) f404334 Handle SyncTransaction in ActivateBestChain instead of ConnectTrace (Matt Corallo) a147687 Keep conflictedTxs in ConnectTrace per-block (Matt Corallo) d3167ba Handle conflicted transactions directly in ConnectTrace (Matt Corallo) 29e6e23 Make ConnectTrace::blocksConnected private, hide behind accessors (Matt Corallo) 822000c Add pblock to connectTrace at the end of ConnectTip, not start (Matt Corallo) f5e9a01 Include missing #include in zmqnotificationinterface.h (Matt Corallo) Tree-SHA512: 8893d47559da3b28d2ef7359768547cba8a4b43b6f891d80f5848f995a84b1517bfb0f706fdc8cd43f09a1350349eb440d9724a59363ab517dfcc4fcb31b2018 --- src/net_processing.cpp | 26 ++--- src/net_processing.h | 8 +- src/rpc/mining.cpp | 9 +- src/validation.cpp | 142 ++++++++++++++------------- src/validationinterface.cpp | 15 +-- src/validationinterface.h | 35 +++---- src/wallet/wallet.cpp | 50 ++++++++-- src/wallet/wallet.h | 18 ++-- src/zmq/zmqnotificationinterface.cpp | 22 ++++- src/zmq/zmqnotificationinterface.h | 5 +- 10 files changed, 196 insertions(+), 134 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 400f4b9342a0..db26aae38ac5 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -806,21 +806,23 @@ PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn) : connman(connmanI recentRejects.reset(new CRollingBloomFilter(120000, 0.000001)); } -void PeerLogicValidation::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int nPosInBlock) { - if (nPosInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK) - return; - +void PeerLogicValidation::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) { LOCK(g_cs_orphans); std::vector vOrphanErase; - // Which orphan pool entries must we evict? - for (size_t j = 0; j < tx.vin.size(); j++) { - auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout); - if (itByPrev == mapOrphanTransactionsByPrev.end()) continue; - for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) { - const CTransaction& orphanTx = *(*mi)->second.tx; - const uint256& orphanHash = orphanTx.GetHash(); - vOrphanErase.push_back(orphanHash); + + for (const CTransactionRef& ptx : pblock->vtx) { + const CTransaction& tx = *ptx; + + // Which orphan pool entries must we evict? + for (size_t j = 0; j < tx.vin.size(); j++) { + auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout); + if (itByPrev == mapOrphanTransactionsByPrev.end()) continue; + for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) { + const CTransaction& orphanTx = *(*mi)->second.tx; + const uint256& orphanHash = orphanTx.GetHash(); + vOrphanErase.push_back(orphanHash); + } } } diff --git a/src/net_processing.h b/src/net_processing.h index aff2d328da6b..b6c0e8ef6436 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -36,10 +36,10 @@ class PeerLogicValidation : public CValidationInterface { public: PeerLogicValidation(CConnman* connmanIn); - virtual void SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int nPosInBlock) override; - virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; - virtual void BlockChecked(const CBlock& block, const CValidationState& state) override; - virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& pblock) override; + void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexConnected, const std::vector& vtxConflicted) override; + void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; + void BlockChecked(const CBlock& block, const CValidationState& state) override; + void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& pblock) override; }; struct CNodeStateStats { diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 1f10cbd5efa6..e855977ceef0 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -37,7 +37,6 @@ #include #include -#include #include @@ -106,7 +105,7 @@ UniValue getnetworkhashps(const JSONRPCRequest& request) } #if ENABLE_MINER -UniValue generateBlocks(boost::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) +UniValue generateBlocks(std::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) { static const int nInnerLoopCount = 0x10000; int nHeightStart = 0; @@ -178,7 +177,7 @@ UniValue generate(const JSONRPCRequest& request) nMaxTries = request.params[1].get_int(); } - boost::shared_ptr coinbaseScript; + std::shared_ptr coinbaseScript; GetMainSignals().ScriptForMining(coinbaseScript); // If the keypool is exhausted, no script is returned at all. Catch this. @@ -219,7 +218,7 @@ UniValue generatetoaddress(const JSONRPCRequest& request) if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address"); - boost::shared_ptr coinbaseScript(new CReserveScript()); + std::shared_ptr coinbaseScript = std::make_shared(); coinbaseScript->reserveScript = GetScriptForDestination(address.Get()); return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false); @@ -752,7 +751,7 @@ class submitblock_StateCatcher : public CValidationInterface submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {} protected: - virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) override { + void BlockChecked(const CBlock& block, const CValidationState& stateIn) override { if (block.GetHash() != hash) return; found = true; diff --git a/src/validation.cpp b/src/validation.cpp index aaa67a55a712..5b3c91b2498b 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -176,39 +176,6 @@ namespace { std::set setDirtyFileInfo; } // anon namespace -/* Use this class to start tracking transactions that are removed from the - * mempool and pass all those transactions through SyncTransaction when the - * object goes out of scope. This is currently only used to call SyncTransaction - * on conflicts removed from the mempool during block connection. Applied in - * ActivateBestChain around ActivateBestStep which in turn calls: - * ConnectTip->removeForBlock->removeConflicts - */ -class MemPoolConflictRemovalTracker -{ -private: - std::vector conflictedTxs; - CTxMemPool &pool; - -public: - MemPoolConflictRemovalTracker(CTxMemPool &_pool) : pool(_pool) { - pool.NotifyEntryRemoved.connect(boost::bind(&MemPoolConflictRemovalTracker::NotifyEntryRemoved, this, _1, _2)); - } - - void NotifyEntryRemoved(CTransactionRef txRemoved, MemPoolRemovalReason reason) { - if (reason == MemPoolRemovalReason::CONFLICT) { - conflictedTxs.push_back(txRemoved); - } - } - - ~MemPoolConflictRemovalTracker() { - pool.NotifyEntryRemoved.disconnect(boost::bind(&MemPoolConflictRemovalTracker::NotifyEntryRemoved, this, _1, _2)); - for (const auto& tx : conflictedTxs) { - GetMainSignals().SyncTransaction(*tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK); - } - conflictedTxs.clear(); - } -}; - CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) { // Find the first block the caller has in the main chain @@ -908,7 +875,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C } if(!fDryRun) - GetMainSignals().SyncTransaction(tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK); + GetMainSignals().TransactionAddedToMempool(ptx); return true; } @@ -2533,7 +2500,8 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); // Read block from disk. - CBlock block; + std::shared_ptr pblock = std::make_shared(); + CBlock& block = *pblock; if (!ReadBlockFromDisk(block, pindexDelete, chainparams.GetConsensus())) return AbortNode(state, "Failed to read block"); // Apply the block atomically to the chain state. @@ -2574,9 +2542,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara UpdateTip(pindexDelete->pprev, chainparams); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: - for (const auto& tx : block.vtx) { - GetMainSignals().SyncTransaction(*tx, pindexDelete->pprev, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK); - } + GetMainSignals().BlockDisconnected(pblock); return true; } @@ -2586,36 +2552,92 @@ static int64_t nTimeFlush = 0; static int64_t nTimeChainState = 0; static int64_t nTimePostConnect = 0; +struct PerBlockConnectTrace { + CBlockIndex* pindex = NULL; + std::shared_ptr pblock; + std::shared_ptr> conflictedTxs; + PerBlockConnectTrace() : conflictedTxs(std::make_shared>()) {} +}; /** * Used to track blocks whose transactions were applied to the UTXO state as a * part of a single ActivateBestChainStep call. + * + * This class also tracks transactions that are removed from the mempool as + * conflicts (per block) and can be used to pass all those transactions + * through SyncTransaction. + * + * This class assumes (and asserts) that the conflicted transactions for a given + * block are added via mempool callbacks prior to the BlockConnected() associated + * with those transactions. If any transactions are marked conflicted, it is + * assumed that an associated block will always be added. + * + * This class is single-use, once you call GetBlocksConnected() you have to throw + * it away and make a new one. */ -struct ConnectTrace { - std::vector > > blocksConnected; +class ConnectTrace { +private: + std::vector blocksConnected; + CTxMemPool &pool; + +public: + ConnectTrace(CTxMemPool &_pool) : blocksConnected(1), pool(_pool) { + pool.NotifyEntryRemoved.connect(boost::bind(&ConnectTrace::NotifyEntryRemoved, this, _1, _2)); + } + + ~ConnectTrace() { + pool.NotifyEntryRemoved.disconnect(boost::bind(&ConnectTrace::NotifyEntryRemoved, this, _1, _2)); + } + + void BlockConnected(CBlockIndex* pindex, std::shared_ptr pblock) { + assert(!blocksConnected.back().pindex); + assert(pindex); + assert(pblock); + blocksConnected.back().pindex = pindex; + blocksConnected.back().pblock = std::move(pblock); + blocksConnected.emplace_back(); + } + + std::vector& GetBlocksConnected() { + // We always keep one extra block at the end of our list because + // blocks are added after all the conflicted transactions have + // been filled in. Thus, the last entry should always be an empty + // one waiting for the transactions from the next block. We pop + // the last entry here to make sure the list we return is sane. + assert(!blocksConnected.back().pindex); + assert(blocksConnected.back().conflictedTxs->empty()); + blocksConnected.pop_back(); + return blocksConnected; + } + + void NotifyEntryRemoved(CTransactionRef txRemoved, MemPoolRemovalReason reason) { + assert(!blocksConnected.back().pindex); + if (reason == MemPoolRemovalReason::CONFLICT) { + blocksConnected.back().conflictedTxs->emplace_back(std::move(txRemoved)); + } + } }; /** * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock * corresponding to pindexNew, to bypass loading it again from disk. * - * The block is always added to connectTrace (either after loading from disk or by copying - * pblock) - if that is not intended, care must be taken to remove the last entry in - * blocksConnected in case of failure. + * The block is added to connectTrace if connection succeeds. */ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr& pblock, ConnectTrace& connectTrace) { assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. int64_t nTime1 = GetTimeMicros(); + std::shared_ptr pthisBlock; if (!pblock) { std::shared_ptr pblockNew = std::make_shared(); - connectTrace.blocksConnected.emplace_back(pindexNew, pblockNew); if (!ReadBlockFromDisk(*pblockNew, pindexNew, chainparams.GetConsensus())) return AbortNode(state, "Failed to read block"); + pthisBlock = pblockNew; } else { - connectTrace.blocksConnected.emplace_back(pindexNew, pblock); + pthisBlock = pblock; } - const CBlock& blockConnecting = *connectTrace.blocksConnected.back().second; + const CBlock& blockConnecting = *pthisBlock; // Apply the block atomically to the chain state. int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1; int64_t nTime3; @@ -2652,6 +2674,8 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; LogPrint(BCLog::BENCHMARK, " - Connect postprocess: %.2fms [%.2fs]\n", (nTime6 - nTime5) * 0.001, nTimePostConnect * 0.000001); LogPrint(BCLog::BENCHMARK, "- Connect block: %.2fms [%.2fs]\n", (nTime6 - nTime1) * 0.001, nTimeTotal * 0.000001); + + connectTrace.BlockConnected(pindexNew, std::move(pthisBlock)); return true; } @@ -2813,8 +2837,6 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c state = CValidationState(); fInvalidFound = true; fContinue = false; - // If we didn't actually connect the block, don't notify listeners about it - connectTrace.blocksConnected.pop_back(); break; } else { // A system error occurred (disk space, database error, ...). @@ -2893,18 +2915,11 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, break; const CBlockIndex *pindexFork; - ConnectTrace connectTrace; bool fInitialDownload; { LOCK(cs_main); - { // TODO: Temporarily ensure that mempool removals are notified before - // connected transactions. This shouldn't matter, but the abandoned - // state of transactions in our wallet is currently cleared when we - // receive another notification and there is a race condition where - // notification of a connected conflict might cause an outside process - // to abandon a transaction and then have it inadvertently cleared by - // the notification that the conflicted transaction was evicted. - MemPoolConflictRemovalTracker mrt(mempool); + ConnectTrace connectTrace(mempool); // Destructed before cs_main is unlocked + CBlockIndex *pindexOldTip = chainActive.Tip(); if (pindexMostWork == NULL) { pindexMostWork = FindMostWorkChain(); @@ -2927,16 +2942,9 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, pindexFork = chainActive.FindFork(pindexOldTip); fInitialDownload = IsInitialBlockDownload(); - // throw all transactions though the signal-interface - - } // MemPoolConflictRemovalTracker destroyed and conflict evictions are notified - - // Transactions in the connected block are notified - for (const auto& pair : connectTrace.blocksConnected) { - assert(pair.second); - const CBlock& block = *(pair.second); - for (unsigned int i = 0; i < block.vtx.size(); i++) - GetMainSignals().SyncTransaction(*block.vtx[i], pair.first, i); + for (const PerBlockConnectTrace& trace : connectTrace.GetBlocksConnected()) { + assert(trace.pblock && trace.pindex); + GetMainSignals().BlockConnected(trace.pblock, trace.pindex, *trace.conflictedTxs); } } // When we reach this point, we switched to a new tip (stored in pindexNewTip). diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 26fc27a2c06b..a29dcbea3f7c 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -16,7 +16,9 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.AcceptedBlockHeader.connect(boost::bind(&CValidationInterface::AcceptedBlockHeader, pwalletIn, _1)); g_signals.NotifyHeaderTip.connect(boost::bind(&CValidationInterface::NotifyHeaderTip, pwalletIn, _1, _2)); g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); - g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3)); + g_signals.TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); + g_signals.BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); + g_signals.BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); g_signals.NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1, _2)); g_signals.NotifyChainLock.connect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1, _2)); g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); @@ -25,7 +27,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); - g_signals.BlockFound.connect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); g_signals.NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); g_signals.NotifyGovernanceObject.connect(boost::bind(&CValidationInterface::NotifyGovernanceObject, pwalletIn, _1)); g_signals.NotifyGovernanceVote.connect(boost::bind(&CValidationInterface::NotifyGovernanceVote, pwalletIn, _1)); @@ -34,7 +35,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { } void UnregisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1)); g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1)); g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); @@ -43,7 +43,9 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.NotifyChainLock.disconnect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1, _2)); g_signals.NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1, _2)); - g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2, _3)); + g_signals.TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); + g_signals.BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); + g_signals.BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); g_signals.NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); g_signals.NotifyHeaderTip.disconnect(boost::bind(&CValidationInterface::NotifyHeaderTip, pwalletIn, _1, _2)); @@ -55,7 +57,6 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { } void UnregisterAllValidationInterfaces() { - g_signals.BlockFound.disconnect_all_slots(); g_signals.ScriptForMining.disconnect_all_slots(); g_signals.BlockChecked.disconnect_all_slots(); g_signals.Broadcast.disconnect_all_slots(); @@ -64,7 +65,9 @@ void UnregisterAllValidationInterfaces() { g_signals.UpdatedTransaction.disconnect_all_slots(); g_signals.NotifyTransactionLock.disconnect_all_slots(); g_signals.NotifyChainLock.disconnect_all_slots(); - g_signals.SyncTransaction.disconnect_all_slots(); + g_signals.TransactionAddedToMempool.disconnect_all_slots(); + g_signals.BlockConnected.disconnect_all_slots(); + g_signals.BlockDisconnected.disconnect_all_slots(); g_signals.UpdatedBlockTip.disconnect_all_slots(); g_signals.NewPoWValidBlock.disconnect_all_slots(); g_signals.NotifyHeaderTip.disconnect_all_slots(); diff --git a/src/validationinterface.h b/src/validationinterface.h index 836d597eaac0..1c189e80b011 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -7,15 +7,15 @@ #define BITCOIN_VALIDATIONINTERFACE_H #include -#include #include +#include "primitives/transaction.h" // CTransaction(Ref) + class CBlock; class CBlockIndex; struct CBlockLocator; class CConnman; class CReserveScript; -class CTransaction; class CValidationInterface; class CValidationState; class CGovernanceVote; @@ -43,7 +43,9 @@ class CValidationInterface { virtual void AcceptedBlockHeader(const CBlockIndex *pindexNew) {} virtual void NotifyHeaderTip(const CBlockIndex *pindexNew, bool fInitialDownload) {} virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} - virtual void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) {} + virtual void TransactionAddedToMempool(const CTransactionRef &ptxn) {} + virtual void BlockConnected(const std::shared_ptr &block, const CBlockIndex *pindex, const std::vector &txnConflicted) {} + virtual void BlockDisconnected(const std::shared_ptr &block) {} virtual void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) {} virtual void NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) {} virtual void NotifyGovernanceVote(const CGovernanceVote &vote) {} @@ -55,8 +57,7 @@ class CValidationInterface { virtual void Inventory(const uint256 &hash) {} virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} - virtual void GetScriptForMining(boost::shared_ptr&) {} - virtual void ResetRequestCount(const uint256 &hash) {} + virtual void GetScriptForMining(std::shared_ptr&) {}; virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr& block) {} friend void ::RegisterValidationInterface(CValidationInterface*); friend void ::UnregisterValidationInterface(CValidationInterface*); @@ -70,17 +71,15 @@ struct CMainSignals { boost::signals2::signal NotifyHeaderTip; /** Notifies listeners of updated block chain tip */ boost::signals2::signal UpdatedBlockTip; - /** A posInBlock value for SyncTransaction calls for transactions not - * included in connected blocks such as transactions removed from mempool, - * accepted to mempool or appearing in disconnected blocks.*/ - static const int SYNC_TRANSACTION_NOT_IN_BLOCK = -1; - /** Notifies listeners of updated transaction data (transaction, and - * optionally the block it is found in). Called with block data when - * transaction is included in a connected block, and without block data when - * transaction was accepted to mempool, removed from mempool (only when - * removal was due to conflict from connected block), or appeared in a - * disconnected block.*/ - boost::signals2::signal SyncTransaction; + /** Notifies listeners of a transaction having been added to mempool. */ + boost::signals2::signal TransactionAddedToMempool; + /** + * Notifies listeners of a block being connected. + * Provides a vector of transactions evicted from the mempool as a result. + */ + boost::signals2::signal &, const CBlockIndex *pindex, const std::vector &)> BlockConnected; + /** Notifies listeners of a block being disconnected */ + boost::signals2::signal &)> BlockDisconnected; /** Notifies listeners of an updated transaction lock without new data. */ boost::signals2::signal NotifyTransactionLock; /** Notifies listeners of a ChainLock. */ @@ -109,9 +108,7 @@ struct CMainSignals { */ boost::signals2::signal BlockChecked; /** Notifies listeners that a key for mining is required (coinbase) */ - boost::signals2::signal&)> ScriptForMining; - /** Notifies listeners that a block has been successfully mined */ - boost::signals2::signal BlockFound; + boost::signals2::signal&)> ScriptForMining; /** * Notifies listeners that a block which builds directly on our current tip * has been received and connected to the headers tree, though not validated yet */ diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index da101d91612b..a6057df14357 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1154,8 +1154,9 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn) * Abandoned state should probably be more carefully tracked via different * posInBlock signals or by checking mempool presence when necessary. */ -bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate) +bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate) { + const CTransaction& tx = *ptx; { AssertLockHeld(cs_wallet); @@ -1176,7 +1177,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex if (fExisted && !fUpdate) return false; if (fExisted || IsMine(tx) || IsFromMe(tx)) { - CWalletTx wtx(this, MakeTransactionRef(tx)); + CWalletTx wtx(this, ptx); // Get merkle branch if transaction was found in a block if (posInBlock != -1) @@ -1310,11 +1311,10 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) fAnonymizableTallyCachedNonDenom = false; } -void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) -{ - LOCK2(cs_main, cs_wallet); +void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindexBlockConnected, int posInBlock) { + const CTransaction& tx = *ptx; - if (!AddToWalletIfInvolvingMe(tx, pindex, posInBlock, true)) + if (!AddToWalletIfInvolvingMe(ptx, pindexBlockConnected, posInBlock, true)) return; // Not one of ours // If a transaction changes 'conflicted' state, that changes the balance @@ -1330,6 +1330,38 @@ void CWallet::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, fAnonymizableTallyCachedNonDenom = false; } +void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) { + LOCK2(cs_main, cs_wallet); + SyncTransaction(ptx, NULL, -1); +} + +void CWallet::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) { + LOCK2(cs_main, cs_wallet); + // TODO: Tempoarily ensure that mempool removals are notified before + // connected transactions. This shouldn't matter, but the abandoned + // state of transactions in our wallet is currently cleared when we + // receive another notification and there is a race condition where + // notification of a connected conflict might cause an outside process + // to abandon a transaction and then have it inadvertantly cleared by + // the notification that the conflicted transaction was evicted. + + for (const CTransactionRef& ptx : vtxConflicted) { + SyncTransaction(ptx, NULL, -1); + } + for (size_t i = 0; i < pblock->vtx.size(); i++) { + SyncTransaction(pblock->vtx[i], pindex, i); + } +} + +void CWallet::BlockDisconnected(const std::shared_ptr& pblock) { + LOCK2(cs_main, cs_wallet); + + for (const CTransactionRef& ptx : pblock->vtx) { + SyncTransaction(ptx, NULL, -1); + } +} + + isminetype CWallet::IsMine(const CTxIn &txin) const { @@ -1856,7 +1888,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f CBlock block; if (ReadBlockFromDisk(block, pindex, Params().GetConsensus())) { for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) { - AddToWalletIfInvolvingMe(*block.vtx[posInBlock], pindex, posInBlock, fUpdate); + AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate); } if (!ret) { ret = pindex; @@ -4483,9 +4515,9 @@ bool CWallet::UpdatedTransaction(const uint256 &hashTx) return false; } -void CWallet::GetScriptForMining(boost::shared_ptr &script) +void CWallet::GetScriptForMining(std::shared_ptr &script) { - boost::shared_ptr rKey(new CReserveKey(this)); + std::shared_ptr rKey = std::make_shared(this); CPubKey pubkey; if (!rKey->GetReservedKey(pubkey, false)) return; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b5543aa8d66c..991fece2b627 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -33,8 +33,6 @@ #include #include -#include - extern CWallet* pwalletMain; /** @@ -715,6 +713,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void SyncMetaData(std::pair); + /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected */ + void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindexBlockConnected, int posInBlock); + /* HD derive new child key (on internal or external chain) */ void DeriveNewChildKey(const CKeyMetadata& metadata, CKey& secretRet, uint32_t nAccountIndex, bool fInternal /*= false*/); @@ -949,8 +950,10 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void MarkDirty(); bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true); bool LoadToWallet(const CWalletTx& wtxIn); - void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) override; - bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); + void TransactionAddedToMempool(const CTransactionRef& tx) override; + void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) override; + void BlockDisconnected(const std::shared_ptr& pblock) override; + bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override; @@ -1069,12 +1072,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface } } - void GetScriptForMining(boost::shared_ptr &script) override; - void ResetRequestCount(const uint256 &hash) override - { - LOCK(cs_wallet); - mapRequestCount[hash] = 0; - }; + void GetScriptForMining(std::shared_ptr &script) override; unsigned int GetKeyPoolSize() { diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 219c95f65889..4593e3ccf67f 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -173,8 +173,12 @@ void CZMQNotificationInterface::NotifyChainLock(const CBlockIndex *pindex, const } } -void CZMQNotificationInterface::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) +void CZMQNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx) { + // Used by BlockConnected and BlockDisconnected as well, because they're + // all the same external callback. + const CTransaction& tx = *ptx; + for (std::list::iterator i = notifiers.begin(); i!=notifiers.end(); ) { CZMQAbstractNotifier *notifier = *i; @@ -190,6 +194,22 @@ void CZMQNotificationInterface::SyncTransaction(const CTransaction& tx, const CB } } +void CZMQNotificationInterface::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexConnected, const std::vector& vtxConflicted) +{ + for (const CTransactionRef& ptx : pblock->vtx) { + // Do a normal notify for each transaction added in the block + TransactionAddedToMempool(ptx); + } +} + +void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr& pblock) +{ + for (const CTransactionRef& ptx : pblock->vtx) { + // Do a normal notify for each transaction removed in block disconnection + TransactionAddedToMempool(ptx); + } +} + void CZMQNotificationInterface::NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) { for (std::list::iterator i = notifiers.begin(); i!=notifiers.end(); ) diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index 6a281d09b808..3cedfe3bf331 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -8,6 +8,7 @@ #include "validationinterface.h" #include #include +#include class CBlockIndex; class CZMQAbstractNotifier; @@ -24,7 +25,9 @@ class CZMQNotificationInterface : public CValidationInterface void Shutdown(); // CValidationInterface - void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) override; + void TransactionAddedToMempool(const CTransactionRef& tx) override; + void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexConnected, const std::vector& vtxConflicted) override; + void BlockDisconnected(const std::shared_ptr& pblock) override; void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; void NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) override; void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) override; From e451325d6dc3ecc3fd9f43d058304a69f3b1f92e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 13 Apr 2017 10:47:42 +0200 Subject: [PATCH 101/987] Merge #10186: Remove SYNC_TRANSACTION_NOT_IN_BLOCK magic number d0cd0bd Make CWallet::SyncTransactions() interface friendlier (John Newbery) 714e4ad AddToWalletIfInvolvingMe should test pIndex, not posInBlock (John Newbery) Tree-SHA512: d02e7ffce635c53f3e099c37cc5613b431f74e0e3ea189269132901a99fc539477849ddad0282ce721d46a4d794c2d46523d58b64f0c26c655f70b5808c745a5 --- src/wallet/wallet.cpp | 20 ++++++++++---------- src/wallet/wallet.h | 5 +++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a6057df14357..282ef35e708f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1144,9 +1144,9 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn) /** * Add a transaction to the wallet, or update it. pIndex and posInBlock should * be set when the transaction was known to be included in a block. When - * posInBlock = SYNC_TRANSACTION_NOT_IN_BLOCK (-1) , then wallet state is not - * updated in AddToWallet, but notifications happen and cached balances are - * marked dirty. + * pIndex == NULL, then wallet state is not updated in AddToWallet, but + * notifications happen and cached balances are marked dirty. + * * If fUpdate is true, existing transactions will be updated. * TODO: One exception to this is that the abandoned state is cleared under the * assumption that any further notification of a transaction that was considered @@ -1160,7 +1160,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI { AssertLockHeld(cs_wallet); - if (posInBlock != -1) { + if (pIndex != NULL) { BOOST_FOREACH(const CTxIn& txin, tx.vin) { std::pair range = mapTxSpends.equal_range(txin.prevout); while (range.first != range.second) { @@ -1180,7 +1180,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI CWalletTx wtx(this, ptx); // Get merkle branch if transaction was found in a block - if (posInBlock != -1) + if (pIndex != NULL) wtx.SetMerkleBranch(pIndex, posInBlock); return AddToWallet(wtx, false); @@ -1311,10 +1311,10 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) fAnonymizableTallyCachedNonDenom = false; } -void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindexBlockConnected, int posInBlock) { +void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pindex, int posInBlock) { const CTransaction& tx = *ptx; - if (!AddToWalletIfInvolvingMe(ptx, pindexBlockConnected, posInBlock, true)) + if (!AddToWalletIfInvolvingMe(ptx, pindex, posInBlock, true)) return; // Not one of ours // If a transaction changes 'conflicted' state, that changes the balance @@ -1332,7 +1332,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pin void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) { LOCK2(cs_main, cs_wallet); - SyncTransaction(ptx, NULL, -1); + SyncTransaction(ptx); } void CWallet::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) { @@ -1346,7 +1346,7 @@ void CWallet::BlockConnected(const std::shared_ptr& pblock, const // the notification that the conflicted transaction was evicted. for (const CTransactionRef& ptx : vtxConflicted) { - SyncTransaction(ptx, NULL, -1); + SyncTransaction(ptx); } for (size_t i = 0; i < pblock->vtx.size(); i++) { SyncTransaction(pblock->vtx[i], pindex, i); @@ -1357,7 +1357,7 @@ void CWallet::BlockDisconnected(const std::shared_ptr& pblock) { LOCK2(cs_main, cs_wallet); for (const CTransactionRef& ptx : pblock->vtx) { - SyncTransaction(ptx, NULL, -1); + SyncTransaction(ptx); } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 991fece2b627..9eb479f4617e 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -713,8 +713,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface void SyncMetaData(std::pair); - /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected */ - void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindexBlockConnected, int posInBlock); + /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected. + * Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */ + void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = NULL, int posInBlock = 0); /* HD derive new child key (on internal or external chain) */ void DeriveNewChildKey(const CKeyMetadata& metadata, CKey& secretRet, uint32_t nAccountIndex, bool fInternal /*= false*/); From 282d1554df4440217c2004100119ca7c4ca4181e Mon Sep 17 00:00:00 2001 From: Pasta Date: Thu, 23 May 2019 09:33:17 -0500 Subject: [PATCH 102/987] adjust examples/dash.conf Signed-off-by: Pasta --- contrib/debian/examples/dash.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/debian/examples/dash.conf b/contrib/debian/examples/dash.conf index 6f5b31255670..fd2ee3c65d00 100644 --- a/contrib/debian/examples/dash.conf +++ b/contrib/debian/examples/dash.conf @@ -135,8 +135,8 @@ # This mode is incompatible with -txindex and -rescan. # 0 = default (no pruning). # 1 = allows manual pruning via RPC. -# >=550 = target to stay under in MiB. -#prune=550 +# >=945 = target to stay under in MiB. +#prune=945 # User interface options From d180061b80c897b86eab67dbcfa9bb8a5b5aa07a Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 23 May 2019 19:16:17 +0300 Subject: [PATCH 103/987] Pass block index via BlockDisconnected --- src/validation.cpp | 2 +- src/validationinterface.cpp | 4 ++-- src/validationinterface.h | 4 ++-- src/wallet/wallet.cpp | 3 ++- src/wallet/wallet.h | 2 +- src/zmq/zmqnotificationinterface.cpp | 2 +- src/zmq/zmqnotificationinterface.h | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 5b3c91b2498b..1c8b57489184 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2542,7 +2542,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara UpdateTip(pindexDelete->pprev, chainparams); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: - GetMainSignals().BlockDisconnected(pblock); + GetMainSignals().BlockDisconnected(pblock, pindexDelete->pprev); return true; } diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index a29dcbea3f7c..d666742eb497 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -18,7 +18,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); g_signals.TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); g_signals.BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); - g_signals.BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); + g_signals.BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1, _2)); g_signals.NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1, _2)); g_signals.NotifyChainLock.connect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1, _2)); g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); @@ -45,7 +45,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1, _2)); g_signals.TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); g_signals.BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); - g_signals.BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); + g_signals.BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1, _2)); g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); g_signals.NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); g_signals.NotifyHeaderTip.disconnect(boost::bind(&CValidationInterface::NotifyHeaderTip, pwalletIn, _1, _2)); diff --git a/src/validationinterface.h b/src/validationinterface.h index 1c189e80b011..4d2d5055e45d 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -45,7 +45,7 @@ class CValidationInterface { virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} virtual void TransactionAddedToMempool(const CTransactionRef &ptxn) {} virtual void BlockConnected(const std::shared_ptr &block, const CBlockIndex *pindex, const std::vector &txnConflicted) {} - virtual void BlockDisconnected(const std::shared_ptr &block) {} + virtual void BlockDisconnected(const std::shared_ptr &block, const CBlockIndex *pindex) {} virtual void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) {} virtual void NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) {} virtual void NotifyGovernanceVote(const CGovernanceVote &vote) {} @@ -79,7 +79,7 @@ struct CMainSignals { */ boost::signals2::signal &, const CBlockIndex *pindex, const std::vector &)> BlockConnected; /** Notifies listeners of a block being disconnected */ - boost::signals2::signal &)> BlockDisconnected; + boost::signals2::signal &, const CBlockIndex* pindex)> BlockDisconnected; /** Notifies listeners of an updated transaction lock without new data. */ boost::signals2::signal NotifyTransactionLock; /** Notifies listeners of a ChainLock. */ diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 282ef35e708f..7a287b52eda6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1353,10 +1353,11 @@ void CWallet::BlockConnected(const std::shared_ptr& pblock, const } } -void CWallet::BlockDisconnected(const std::shared_ptr& pblock) { +void CWallet::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) { LOCK2(cs_main, cs_wallet); for (const CTransactionRef& ptx : pblock->vtx) { + // NOTE: do NOT pass pindex here SyncTransaction(ptx); } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 9eb479f4617e..1ca695ae4ab1 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -953,7 +953,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool LoadToWallet(const CWalletTx& wtxIn); void TransactionAddedToMempool(const CTransactionRef& tx) override; void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) override; - void BlockDisconnected(const std::shared_ptr& pblock) override; + void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) override; bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 4593e3ccf67f..6e583b7bb1d5 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -202,7 +202,7 @@ void CZMQNotificationInterface::BlockConnected(const std::shared_ptr& pblock) +void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) { for (const CTransactionRef& ptx : pblock->vtx) { // Do a normal notify for each transaction removed in block disconnection diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index 3cedfe3bf331..75eb51416afa 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -27,7 +27,7 @@ class CZMQNotificationInterface : public CValidationInterface // CValidationInterface void TransactionAddedToMempool(const CTransactionRef& tx) override; void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexConnected, const std::vector& vtxConflicted) override; - void BlockDisconnected(const std::shared_ptr& pblock) override; + void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) override; void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; void NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) override; void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) override; From 250195185f673ee99a2c196b38f85ec2307f25e2 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 23 May 2019 19:22:37 +0300 Subject: [PATCH 104/987] Adjust CDSNotificationInterface to align with CValidationInterface changes --- src/dsnotificationinterface.cpp | 32 +++++++++++++++++++++++++++++++- src/dsnotificationinterface.h | 6 +++++- src/instantsend.cpp | 10 +++++----- src/instantsend.h | 2 +- src/llmq/quorums_chainlocks.cpp | 10 +++++----- src/llmq/quorums_chainlocks.h | 2 +- src/llmq/quorums_instantsend.cpp | 22 +++++++++++----------- src/llmq/quorums_instantsend.h | 2 +- src/privatesend/privatesend.cpp | 8 ++++---- src/privatesend/privatesend.h | 2 +- 10 files changed, 65 insertions(+), 31 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 684a63df9be5..717b197b73fa 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -72,7 +72,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con llmq::quorumDKGSessionManager->UpdatedBlockTip(pindexNew, fInitialDownload); } -void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock) +void CDSNotificationInterface::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { llmq::quorumInstantSendManager->SyncTransaction(tx, pindex, posInBlock); llmq::chainLocksHandler->SyncTransaction(tx, pindex, posInBlock); @@ -80,6 +80,36 @@ void CDSNotificationInterface::SyncTransaction(const CTransaction &tx, const CBl CPrivateSend::SyncTransaction(tx, pindex, posInBlock); } +void CDSNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx) +{ + SyncTransaction(ptx); +} + +void CDSNotificationInterface::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) +{ + // TODO: Tempoarily ensure that mempool removals are notified before + // connected transactions. This shouldn't matter, but the abandoned + // state of transactions in our wallet is currently cleared when we + // receive another notification and there is a race condition where + // notification of a connected conflict might cause an outside process + // to abandon a transaction and then have it inadvertantly cleared by + // the notification that the conflicted transaction was evicted. + + for (const CTransactionRef& ptx : vtxConflicted) { + SyncTransaction(ptx); + } + for (size_t i = 0; i < pblock->vtx.size(); i++) { + SyncTransaction(pblock->vtx[i], pindex, i); + } +} + +void CDSNotificationInterface::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) +{ + for (const CTransactionRef& ptx : pblock->vtx) { + SyncTransaction(ptx, pindex, -1); + } +} + void CDSNotificationInterface::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) { CMNAuth::NotifyMasternodeListChanged(undo, oldMNList, diff); diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h index 44873b2b0691..63fd2e978a4b 100644 --- a/src/dsnotificationinterface.h +++ b/src/dsnotificationinterface.h @@ -21,12 +21,16 @@ class CDSNotificationInterface : public CValidationInterface void AcceptedBlockHeader(const CBlockIndex *pindexNew) override; 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 TransactionAddedToMempool(const CTransactionRef& tx) override; + void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) override; + void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) override; void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) override; void NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) override; private: CConnman& connman; + /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected */ + void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); }; #endif // BITCOIN_DSNOTIFICATIONINTERFACE_H diff --git a/src/instantsend.cpp b/src/instantsend.cpp index 5caf89eeca5a..ff5bf3d7df47 100644 --- a/src/instantsend.cpp +++ b/src/instantsend.cpp @@ -882,19 +882,19 @@ void CInstantSend::UpdatedBlockTip(const CBlockIndex *pindex) nCachedBlockHeight = pindex->nHeight; } -void CInstantSend::SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock) +void CInstantSend::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { // Update lock candidates and votes if corresponding tx confirmed // or went from confirmed to 0-confirmed or conflicted. - if (tx.IsCoinBase()) return; + if (tx->IsCoinBase()) return; LOCK2(cs_main, cs_instantsend); - uint256 txHash = tx.GetHash(); + uint256 txHash = tx->GetHash(); - // When tx is 0-confirmed or conflicted, posInBlock is SYNC_TRANSACTION_NOT_IN_BLOCK and nHeightNew should be set to -1 - int nHeightNew = posInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK ? -1 : pindex->nHeight; + // When tx is 0-confirmed or conflicted, posInBlock is -1 and nHeightNew should be set to -1 + int nHeightNew = (posInBlock == -1 || pindex == nullptr) ? -1 : pindex->nHeight; LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d\n", txHash.ToString(), nHeightNew); diff --git a/src/instantsend.h b/src/instantsend.h index 9fef88e05249..49006ce4e243 100644 --- a/src/instantsend.h +++ b/src/instantsend.h @@ -148,7 +148,7 @@ class CInstantSend void Relay(const uint256& txHash, CConnman& connman); void UpdatedBlockTip(const CBlockIndex *pindex); - void SyncTransaction(const CTransaction& tx, const CBlockIndex *pindex, int posInBlock); + void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); std::string ToString() const; diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 48dded9332d7..7ced03cd892f 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -345,14 +345,14 @@ void CChainLocksHandler::TrySignChainTip() quorumSigningManager->AsyncSignIfMember(Params().GetConsensus().llmqChainLocks, requestId, msgHash); } -void CChainLocksHandler::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) +void CChainLocksHandler::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { if (!masternodeSync.IsBlockchainSynced()) { return; } bool handleTx = true; - if (tx.IsCoinBase() || tx.vin.empty()) { + if (tx->IsCoinBase() || tx->vin.empty()) { handleTx = false; } @@ -360,13 +360,13 @@ void CChainLocksHandler::SyncTransaction(const CTransaction& tx, const CBlockInd if (handleTx) { int64_t curTime = GetAdjustedTime(); - txFirstSeenTime.emplace(tx.GetHash(), curTime); + txFirstSeenTime.emplace(tx->GetHash(), curTime); } // We listen for SyncTransaction so that we can collect all TX ids of all included TXs of newly received blocks // We need this information later when we try to sign a new tip, so that we can determine if all included TXs are // safe. - if (pindex && posInBlock != CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK) { + if (pindex != nullptr && posInBlock != -1) { auto it = blockTxs.find(pindex->GetBlockHash()); if (it == blockTxs.end()) { // we want this to be run even if handleTx == false, so that the coinbase TX triggers creation of an empty entry @@ -374,7 +374,7 @@ void CChainLocksHandler::SyncTransaction(const CTransaction& tx, const CBlockInd } if (handleTx) { auto& txs = *it->second; - txs.emplace(tx.GetHash()); + txs.emplace(tx->GetHash()); } } } diff --git a/src/llmq/quorums_chainlocks.h b/src/llmq/quorums_chainlocks.h index 98378f7a1447..148fdf35dbdc 100644 --- a/src/llmq/quorums_chainlocks.h +++ b/src/llmq/quorums_chainlocks.h @@ -90,7 +90,7 @@ class CChainLocksHandler : public CRecoveredSigsListener void ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash); void AcceptedBlockHeader(const CBlockIndex* pindexNew); void UpdatedBlockTip(const CBlockIndex* pindexNew); - void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock); + void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); void CheckActiveState(); void TrySignChainTip(); void EnforceBestChainLock(); diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index e6d859c714ef..24ce9f39eb74 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -949,38 +949,38 @@ void CInstantSendManager::UpdateWalletTransaction(const CTransactionRef& tx, con mempool.AddTransactionsUpdated(1); } -void CInstantSendManager::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) +void CInstantSendManager::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { if (!IsNewInstantSendEnabled()) { return; } - if (tx.IsCoinBase() || tx.vin.empty()) { + if (tx->IsCoinBase() || tx->vin.empty()) { // coinbase can't and TXs with no inputs be locked return; } - bool inMempool = mempool.get(tx.GetHash()) != nullptr; + bool inMempool = mempool.get(tx->GetHash()) != nullptr; // Are we called from validation.cpp/MemPoolConflictRemovalTracker? // TODO refactor this when we backport the BlockConnected signal from Bitcoin, as it gives better info about // conflicted TXs - bool isConflictRemoved = !pindex && posInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK && !inMempool; + bool isConflictRemoved = pindex == nullptr && posInBlock == -1 && !inMempool; if (isConflictRemoved) { LOCK(cs); - RemoveConflictedTx(tx); + RemoveConflictedTx(*tx); return; } uint256 islockHash; { LOCK(cs); - islockHash = db.GetInstantSendLockHashByTxid(tx.GetHash()); + islockHash = db.GetInstantSendLockHashByTxid(tx->GetHash()); // update DB about when an IS lock was mined if (!islockHash.IsNull() && pindex) { - if (posInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK) { + if (posInBlock == -1) { db.RemoveInstantSendLockMined(islockHash, pindex->nHeight); } else { db.WriteInstantSendLockMined(islockHash, pindex->nHeight); @@ -994,17 +994,17 @@ void CInstantSendManager::SyncTransaction(const CTransaction& tx, const CBlockIn bool chainlocked = pindex && chainLocksHandler->HasChainLock(pindex->nHeight, pindex->GetBlockHash()); if (islockHash.IsNull() && !chainlocked) { - ProcessTx(tx, Params().GetConsensus()); + ProcessTx(*tx, Params().GetConsensus()); } LOCK(cs); if (!chainlocked && islockHash.IsNull()) { // TX is not locked, so make sure it is tracked - AddNonLockedTx(MakeTransactionRef(tx)); - nonLockedTxs.at(tx.GetHash()).pindexMined = posInBlock != CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK ? pindex : nullptr; + AddNonLockedTx(tx); + nonLockedTxs.at(tx->GetHash()).pindexMined = posInBlock != -1 ? pindex : nullptr; } else { // TX is locked, so make sure we don't track it anymore - RemoveNonLockedTx(tx.GetHash(), true); + RemoveNonLockedTx(tx->GetHash(), true); } } diff --git a/src/llmq/quorums_instantsend.h b/src/llmq/quorums_instantsend.h index 4622ef8b0ac5..4f2811c6b09b 100644 --- a/src/llmq/quorums_instantsend.h +++ b/src/llmq/quorums_instantsend.h @@ -141,7 +141,7 @@ class CInstantSendManager : public CRecoveredSigsListener void ProcessInstantSendLock(NodeId from, const uint256& hash, const CInstantSendLock& islock); void UpdateWalletTransaction(const CTransactionRef& tx, const CInstantSendLock& islock); - void SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock); + void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); void AddNonLockedTx(const CTransactionRef& tx); void RemoveNonLockedTx(const uint256& txid, bool retryChildren); void RemoveConflictedTx(const CTransaction& tx); diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 527aad92dc95..8a7b9ffc01a8 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -509,16 +509,16 @@ void CPrivateSend::UpdatedBlockTip(const CBlockIndex* pindex) } } -void CPrivateSend::SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock) +void CPrivateSend::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { - if (tx.IsCoinBase()) return; + if (tx->IsCoinBase()) return; LOCK2(cs_main, cs_mapdstx); - uint256 txHash = tx.GetHash(); + uint256 txHash = tx->GetHash(); if (!mapDSTX.count(txHash)) return; // When tx is 0-confirmed or conflicted, posInBlock is SYNC_TRANSACTION_NOT_IN_BLOCK and nConfirmedHeight should be set to -1 - mapDSTX[txHash].SetConfirmedHeight(posInBlock == CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK ? -1 : pindex->nHeight); + mapDSTX[txHash].SetConfirmedHeight((posInBlock == -1 || pindex == nullptr) ? -1 : pindex->nHeight); LogPrint(BCLog::PRIVATESEND, "CPrivateSend::SyncTransaction -- txid=%s\n", txHash.ToString()); } diff --git a/src/privatesend/privatesend.h b/src/privatesend/privatesend.h index 65f7fb3436cc..4ff8562779f1 100644 --- a/src/privatesend/privatesend.h +++ b/src/privatesend/privatesend.h @@ -422,7 +422,7 @@ class CPrivateSend static CPrivateSendBroadcastTx GetDSTX(const uint256& hash); static void UpdatedBlockTip(const CBlockIndex* pindex); - static void SyncTransaction(const CTransaction& tx, const CBlockIndex* pindex, int posInBlock); + static void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); }; #endif From 9b8a750c95d58dd066fc9235b271a18c9d180c98 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 24 May 2019 15:53:24 +0300 Subject: [PATCH 105/987] More `boost::filesystem`->`fs` and some related cleanup --- src/dash-cli.cpp | 2 +- src/dashd.cpp | 2 +- src/dbwrapper.h | 2 -- src/flat-database.h | 7 +++---- src/init.cpp | 2 +- src/qt/guiutil.cpp | 8 ++++---- src/test/alert_tests.cpp | 10 +++++----- src/util.cpp | 4 +--- src/util.h | 2 +- src/wallet/wallet.cpp | 4 +--- 10 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/dash-cli.cpp b/src/dash-cli.cpp index b9fb7b777d85..5c9070034d91 100644 --- a/src/dash-cli.cpp +++ b/src/dash-cli.cpp @@ -109,7 +109,7 @@ static int AppInitRPC(int argc, char* argv[]) fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return EXIT_FAILURE; } - if (!datadirFromCmdLine && !boost::filesystem::is_directory(GetDataDir(false))) { + if (!datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified data directory \"%s\" from config file does not exist.\n", GetArg("-datadir", "").c_str()); return EXIT_FAILURE; } diff --git a/src/dashd.cpp b/src/dashd.cpp index c67891d547b4..025387b95e9a 100644 --- a/src/dashd.cpp +++ b/src/dashd.cpp @@ -112,7 +112,7 @@ bool AppInit(int argc, char* argv[]) fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; } - if (!datadirFromCmdLine && !boost::filesystem::is_directory(GetDataDir(false))) + if (!datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified data directory \"%s\" from config file does not exist.\n", GetArg("-datadir", "").c_str()); return EXIT_FAILURE; diff --git a/src/dbwrapper.h b/src/dbwrapper.h index f6970bc42421..7033b2b2539f 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -15,8 +15,6 @@ #include -#include - #include #include diff --git a/src/flat-database.h b/src/flat-database.h index 218c4b2df510..d97ef517be74 100644 --- a/src/flat-database.h +++ b/src/flat-database.h @@ -7,12 +7,11 @@ #include "chainparams.h" #include "clientversion.h" +#include "fs.h" #include "hash.h" #include "streams.h" #include "util.h" -#include - /** * Generic Dumping and Loading * --------------------------- @@ -33,7 +32,7 @@ class CFlatDB IncorrectFormat }; - boost::filesystem::path pathDB; + fs::path pathDB; std::string strFilename; std::string strMagicMessage; @@ -87,7 +86,7 @@ class CFlatDB } // use file size to size memory buffer - int fileSize = boost::filesystem::file_size(pathDB); + int fileSize = fs::file_size(pathDB); int dataSize = fileSize - sizeof(uint256); // Don't try to resize to a negative number if file is small if (dataSize < 0) diff --git a/src/init.cpp b/src/init.cpp index 05acb8758968..c102c9c861a7 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2025,7 +2025,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) bool fIgnoreCacheFiles = fLiteMode || fReindex || fReindexChainState; if (!fIgnoreCacheFiles) { - boost::filesystem::path pathDB = GetDataDir(); + fs::path pathDB = GetDataDir(); std::string strDBName; strDBName = "mncache.dat"; diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 1e75eb60f397..7ae5bfcd3974 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -434,19 +434,19 @@ void openDebugLogfile() void openConfigfile() { - boost::filesystem::path pathConfig = GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)); + fs::path pathConfig = GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)); /* Open dash.conf with the associated application */ - if (boost::filesystem::exists(pathConfig)) + if (fs::exists(pathConfig)) QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(pathConfig))); } void showBackups() { - boost::filesystem::path backupsDir = GetBackupsDir(); + fs::path backupsDir = GetBackupsDir(); /* Open folder with default browser */ - if (boost::filesystem::exists(backupsDir)) + if (fs::exists(backupsDir)) QDesktopServices::openUrl(QUrl::fromLocalFile(boostPathToQString(backupsDir))); } diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index 1cfc894e6a23..a2a2d9d96d0e 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -9,6 +9,7 @@ #include "chainparams.h" #include "clientversion.h" #include "data/alertTests.raw.h" +#include "fs.h" #include "serialize.h" #include "streams.h" #include "utilstrencodings.h" @@ -18,7 +19,6 @@ #include -#include #include // @@ -123,7 +123,7 @@ struct ReadAlerts : public TestingSetup } ~ReadAlerts() { } - static std::vector read_lines(boost::filesystem::path filepath) + static std::vector read_lines(fs::path filepath) { std::vector result; @@ -202,8 +202,8 @@ BOOST_AUTO_TEST_CASE(AlertNotify) SetMockTime(11); const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - boost::filesystem::path temp = GetTempPath() / - boost::filesystem::unique_path("alertnotify-%%%%.txt"); + fs::path temp = GetTempPath() / + fs::unique_path("alertnotify-%%%%.txt"); ForceSetArg("-alertnotify", std::string("echo %s >> ") + temp.string()); @@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(AlertNotify) BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' "); BOOST_CHECK_EQUAL(r[3], "'Evil Alert; /bin/ls; echo ' "); #endif - boost::filesystem::remove(temp); + fs::remove(temp); SetMockTime(0); } diff --git a/src/util.cpp b/src/util.cpp index 360322a8c308..3f89b7b740f9 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -667,10 +667,8 @@ const fs::path &GetDataDir(bool fNetSpecific) return path; } -boost::filesystem::path GetBackupsDir() +fs::path GetBackupsDir() { - namespace fs = boost::filesystem; - if (!IsArgSet("-walletbackupsdir")) return GetDataDir() / "backups"; diff --git a/src/util.h b/src/util.h index 511ca00d1e8b..fb8033d8c97b 100644 --- a/src/util.h +++ b/src/util.h @@ -201,7 +201,7 @@ bool RenameOver(fs::path src, fs::path dest); bool TryCreateDirectory(const fs::path& p); fs::path GetDefaultDataDir(); const fs::path &GetDataDir(bool fNetSpecific = true); -boost::filesystem::path GetBackupsDir(); +fs::path GetBackupsDir(); void ClearDatadirCache(); fs::path GetConfigFile(const std::string& confPath); #ifndef WIN32 diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 7a287b52eda6..12cea8334596 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5155,7 +5155,7 @@ bool CWallet::ParameterInteraction() bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); if (IsArgSet("-walletbackupsdir")) { - if (!boost::filesystem::is_directory(GetArg("-walletbackupsdir", ""))) { + if (!fs::is_directory(GetArg("-walletbackupsdir", ""))) { LogPrintf("%s: Warning: incorrect parameter -walletbackupsdir, path must exist! Using default path.\n", __func__); InitWarning("Warning: incorrect parameter -walletbackupsdir, path must exist! Using default path.\n"); @@ -5229,8 +5229,6 @@ bool CWallet::BackupWallet(const std::string& strDest) // either supply "wallet" (if already loaded) or "strWalletFile" (if wallet wasn't loaded yet) bool AutoBackupWallet(CWallet* wallet, const std::string& strWalletFile_, std::string& strBackupWarningRet, std::string& strBackupErrorRet) { - namespace fs = boost::filesystem; - strBackupWarningRet = strBackupErrorRet = ""; std::string strWalletFile = ""; From 6afa605f6f680193a134212a06949b85a73032e3 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 14:55:29 +0200 Subject: [PATCH 106/987] Pass disconnected/deleted pindex instead of pprev into BlockDisconnected CDSNotificationInterface::BlockDisconnected still calls SyncTransaction with pprev to keep compatibility. --- src/dsnotificationinterface.cpp | 4 ++-- src/dsnotificationinterface.h | 2 +- src/validation.cpp | 2 +- src/validationinterface.h | 4 ++-- src/wallet/wallet.cpp | 2 +- src/wallet/wallet.h | 2 +- src/zmq/zmqnotificationinterface.cpp | 2 +- src/zmq/zmqnotificationinterface.h | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 717b197b73fa..33cc5e8e77bb 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -103,10 +103,10 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) +void CDSNotificationInterface::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) { for (const CTransactionRef& ptx : pblock->vtx) { - SyncTransaction(ptx, pindex, -1); + SyncTransaction(ptx, pindexDisconnected->pprev, -1); } } diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h index 63fd2e978a4b..b8f480725d85 100644 --- a/src/dsnotificationinterface.h +++ b/src/dsnotificationinterface.h @@ -23,7 +23,7 @@ class CDSNotificationInterface : public CValidationInterface void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; void TransactionAddedToMempool(const CTransactionRef& tx) override; void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) override; - void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) override; + void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) override; void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) override; void NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) override; diff --git a/src/validation.cpp b/src/validation.cpp index 1c8b57489184..f7627fd40914 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2542,7 +2542,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara UpdateTip(pindexDelete->pprev, chainparams); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: - GetMainSignals().BlockDisconnected(pblock, pindexDelete->pprev); + GetMainSignals().BlockDisconnected(pblock, pindexDelete); return true; } diff --git a/src/validationinterface.h b/src/validationinterface.h index 4d2d5055e45d..0ca3dba23041 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -45,7 +45,7 @@ class CValidationInterface { virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) {} virtual void TransactionAddedToMempool(const CTransactionRef &ptxn) {} virtual void BlockConnected(const std::shared_ptr &block, const CBlockIndex *pindex, const std::vector &txnConflicted) {} - virtual void BlockDisconnected(const std::shared_ptr &block, const CBlockIndex *pindex) {} + virtual void BlockDisconnected(const std::shared_ptr &block, const CBlockIndex *pindexDisconnected) {} virtual void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) {} virtual void NotifyChainLock(const CBlockIndex* pindex, const llmq::CChainLockSig& clsig) {} virtual void NotifyGovernanceVote(const CGovernanceVote &vote) {} @@ -79,7 +79,7 @@ struct CMainSignals { */ boost::signals2::signal &, const CBlockIndex *pindex, const std::vector &)> BlockConnected; /** Notifies listeners of a block being disconnected */ - boost::signals2::signal &, const CBlockIndex* pindex)> BlockDisconnected; + boost::signals2::signal &, const CBlockIndex* pindexDisconnected)> BlockDisconnected; /** Notifies listeners of an updated transaction lock without new data. */ boost::signals2::signal NotifyTransactionLock; /** Notifies listeners of a ChainLock. */ diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 12cea8334596..71a0c76c9ce6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1353,7 +1353,7 @@ void CWallet::BlockConnected(const std::shared_ptr& pblock, const } } -void CWallet::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) { +void CWallet::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) { LOCK2(cs_main, cs_wallet); for (const CTransactionRef& ptx : pblock->vtx) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 1ca695ae4ab1..aec951cf3a47 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -953,7 +953,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool LoadToWallet(const CWalletTx& wtxIn); void TransactionAddedToMempool(const CTransactionRef& tx) override; void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) override; - void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) override; + void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) override; bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate); CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false); void ReacceptWalletTransactions(); diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 6e583b7bb1d5..c5623ed800ae 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -202,7 +202,7 @@ void CZMQNotificationInterface::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) +void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) { for (const CTransactionRef& ptx : pblock->vtx) { // Do a normal notify for each transaction removed in block disconnection diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index 75eb51416afa..ab05b9d7e931 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -27,7 +27,7 @@ class CZMQNotificationInterface : public CValidationInterface // CValidationInterface void TransactionAddedToMempool(const CTransactionRef& tx) override; void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexConnected, const std::vector& vtxConflicted) override; - void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindex) override; + void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) override; void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; void NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig& clsig) override; void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock& islock) override; From b36f0a324f2446a326339bd15a238f4af74c7e6a Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 13:35:22 +0200 Subject: [PATCH 107/987] Call new signals instead of SyncTransaction on CInstantSendManager This commit moves all logic of SyncTransaction into ProcessNewTransaction and then calls it from TransactionAddedToMempool and BlockConnected. This won't compile/work at first, but the next commits will fix this. --- src/dsnotificationinterface.cpp | 6 +++++- src/llmq/quorums_instantsend.cpp | 22 +++++++++++++++++++++- src/llmq/quorums_instantsend.h | 5 ++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 33cc5e8e77bb..0a18570d424a 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -74,7 +74,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con void CDSNotificationInterface::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { - llmq::quorumInstantSendManager->SyncTransaction(tx, pindex, posInBlock); llmq::chainLocksHandler->SyncTransaction(tx, pindex, posInBlock); instantsend.SyncTransaction(tx, pindex, posInBlock); CPrivateSend::SyncTransaction(tx, pindex, posInBlock); @@ -82,6 +81,7 @@ void CDSNotificationInterface::SyncTransaction(const CTransactionRef& tx, const void CDSNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx) { + llmq::quorumInstantSendManager->TransactionAddedToMempool(ptx); SyncTransaction(ptx); } @@ -95,6 +95,8 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptrBlockConnected(pblock, pindex, vtxConflicted); + for (const CTransactionRef& ptx : vtxConflicted) { SyncTransaction(ptx); } @@ -105,6 +107,8 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) { + llmq::quorumInstantSendManager->BlockDisconnected(pblock, pindexDisconnected); + for (const CTransactionRef& ptx : pblock->vtx) { SyncTransaction(ptx, pindexDisconnected->pprev, -1); } diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 24ce9f39eb74..dd16533ef4a1 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -949,7 +949,7 @@ void CInstantSendManager::UpdateWalletTransaction(const CTransactionRef& tx, con mempool.AddTransactionsUpdated(1); } -void CInstantSendManager::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) +void CInstantSendManager::ProcessNewTransaction(const CTransactionRef& tx, const CBlockIndex* pindex) { if (!IsNewInstantSendEnabled()) { return; @@ -1008,6 +1008,26 @@ void CInstantSendManager::SyncTransaction(const CTransactionRef& tx, const CBloc } } +void CInstantSendManager::TransactionAddedToMempool(const CTransactionRef& tx) +{ + ProcessNewTransaction(tx, nullptr); +} + +void CInstantSendManager::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) +{ + if (!IsNewInstantSendEnabled()) { + return; + } + + for (const auto& tx : pblock->vtx) { + ProcessNewTransaction(tx, pindex); + } +} + +void CInstantSendManager::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) +{ +} + void CInstantSendManager::AddNonLockedTx(const CTransactionRef& tx) { AssertLockHeld(cs); diff --git a/src/llmq/quorums_instantsend.h b/src/llmq/quorums_instantsend.h index 4f2811c6b09b..4ba1e3a678bc 100644 --- a/src/llmq/quorums_instantsend.h +++ b/src/llmq/quorums_instantsend.h @@ -141,7 +141,10 @@ class CInstantSendManager : public CRecoveredSigsListener void ProcessInstantSendLock(NodeId from, const uint256& hash, const CInstantSendLock& islock); void UpdateWalletTransaction(const CTransactionRef& tx, const CInstantSendLock& islock); - void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); + void ProcessNewTransaction(const CTransactionRef& tx, const CBlockIndex* pindex); + void TransactionAddedToMempool(const CTransactionRef& tx); + void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted); + void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected); void AddNonLockedTx(const CTransactionRef& tx); void RemoveNonLockedTx(const uint256& txid, bool retryChildren); void RemoveConflictedTx(const CTransaction& tx); From b645757be9f83e7cfe5a3df2cda3b4509a868b8f Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 13:40:18 +0200 Subject: [PATCH 108/987] Call RemoveConflictedTx from BlockConnected instead of ProcessNewTransaction --- src/llmq/quorums_instantsend.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index dd16533ef4a1..05e230254241 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -962,17 +962,6 @@ void CInstantSendManager::ProcessNewTransaction(const CTransactionRef& tx, const bool inMempool = mempool.get(tx->GetHash()) != nullptr; - // Are we called from validation.cpp/MemPoolConflictRemovalTracker? - // TODO refactor this when we backport the BlockConnected signal from Bitcoin, as it gives better info about - // conflicted TXs - bool isConflictRemoved = pindex == nullptr && posInBlock == -1 && !inMempool; - - if (isConflictRemoved) { - LOCK(cs); - RemoveConflictedTx(*tx); - return; - } - uint256 islockHash; { LOCK(cs); @@ -1019,6 +1008,13 @@ void CInstantSendManager::BlockConnected(const std::shared_ptr& pb return; } + if (!vtxConflicted.empty()) { + LOCK(cs); + for (const auto& tx : vtxConflicted) { + RemoveConflictedTx(*tx); + } + } + for (const auto& tx : pblock->vtx) { ProcessNewTransaction(tx, pindex); } From 0b4f7b9b6d375719ffff2f2366b0079ee6ddc734 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 13:42:49 +0200 Subject: [PATCH 109/987] Move removal of mined-locks info to BlockDisconnected --- src/llmq/quorums_instantsend.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 05e230254241..cb2fa1d3276f 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -969,11 +969,7 @@ void CInstantSendManager::ProcessNewTransaction(const CTransactionRef& tx, const // update DB about when an IS lock was mined if (!islockHash.IsNull() && pindex) { - if (posInBlock == -1) { - db.RemoveInstantSendLockMined(islockHash, pindex->nHeight); - } else { - db.WriteInstantSendLockMined(islockHash, pindex->nHeight); - } + db.WriteInstantSendLockMined(islockHash, pindex->nHeight); } } @@ -1022,6 +1018,13 @@ void CInstantSendManager::BlockConnected(const std::shared_ptr& pb void CInstantSendManager::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) { + LOCK(cs); + for (auto& tx : pblock->vtx) { + auto islockHash = db.GetInstantSendLockHashByTxid(tx->GetHash()); + if (!islockHash.IsNull()) { + db.RemoveInstantSendLockMined(islockHash, pindexDisconnected->nHeight); + } + } } void CInstantSendManager::AddNonLockedTx(const CTransactionRef& tx) From 523304537345dd17c6ebba538a185023cb1d8f98 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 13:43:57 +0200 Subject: [PATCH 110/987] Don't check for posInBlock when updating pindexMined ProcessNewTransaction is now only called with pindex != nullptr when a block is connected but never when it is disconnected, so there is no need to check for posInBlock anymore (we don't even have it now). --- src/llmq/quorums_instantsend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index cb2fa1d3276f..1e5333e0f90d 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -986,7 +986,7 @@ void CInstantSendManager::ProcessNewTransaction(const CTransactionRef& tx, const if (!chainlocked && islockHash.IsNull()) { // TX is not locked, so make sure it is tracked AddNonLockedTx(tx); - nonLockedTxs.at(tx->GetHash()).pindexMined = posInBlock != -1 ? pindex : nullptr; + nonLockedTxs.at(tx->GetHash()).pindexMined = pindex; } else { // TX is locked, so make sure we don't track it anymore RemoveNonLockedTx(tx->GetHash(), true); From 25c40fe40943fa6726574e7c6a2384007a587afa Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 13:44:52 +0200 Subject: [PATCH 111/987] Fix typo --- src/llmq/quorums_instantsend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 1e5333e0f90d..5ec2710fcc64 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -956,7 +956,7 @@ void CInstantSendManager::ProcessNewTransaction(const CTransactionRef& tx, const } if (tx->IsCoinBase() || tx->vin.empty()) { - // coinbase can't and TXs with no inputs be locked + // coinbase and TXs with no inputs can't be locked return; } From d4e75abbfdcb300d086d56465a939aa51c08e135 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 13:48:01 +0200 Subject: [PATCH 112/987] Call new signals in CChainLocksHandler --- src/dsnotificationinterface.cpp | 4 +++- src/llmq/quorums_chainlocks.cpp | 15 +++++++++++++++ src/llmq/quorums_chainlocks.h | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 0a18570d424a..233961a469ce 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -74,7 +74,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con void CDSNotificationInterface::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { - llmq::chainLocksHandler->SyncTransaction(tx, pindex, posInBlock); instantsend.SyncTransaction(tx, pindex, posInBlock); CPrivateSend::SyncTransaction(tx, pindex, posInBlock); } @@ -82,6 +81,7 @@ void CDSNotificationInterface::SyncTransaction(const CTransactionRef& tx, const void CDSNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx) { llmq::quorumInstantSendManager->TransactionAddedToMempool(ptx); + llmq::chainLocksHandler->TransactionAddedToMempool(ptx); SyncTransaction(ptx); } @@ -96,6 +96,7 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptrBlockConnected(pblock, pindex, vtxConflicted); + llmq::chainLocksHandler->BlockConnected(pblock, pindex, vtxConflicted); for (const CTransactionRef& ptx : vtxConflicted) { SyncTransaction(ptx); @@ -108,6 +109,7 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) { llmq::quorumInstantSendManager->BlockDisconnected(pblock, pindexDisconnected); + llmq::chainLocksHandler->BlockDisconnected(pblock, pindexDisconnected); for (const CTransactionRef& ptx : pblock->vtx) { SyncTransaction(ptx, pindexDisconnected->pprev, -1); diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 7ced03cd892f..bcde11266593 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -345,6 +345,21 @@ void CChainLocksHandler::TrySignChainTip() quorumSigningManager->AsyncSignIfMember(Params().GetConsensus().llmqChainLocks, requestId, msgHash); } +void CChainLocksHandler::TransactionAddedToMempool(const CTransactionRef& tx) +{ + +} + +void CChainLocksHandler::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) +{ + +} + +void CChainLocksHandler::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) +{ + +} + void CChainLocksHandler::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { if (!masternodeSync.IsBlockchainSynced()) { diff --git a/src/llmq/quorums_chainlocks.h b/src/llmq/quorums_chainlocks.h index 148fdf35dbdc..684a4b838520 100644 --- a/src/llmq/quorums_chainlocks.h +++ b/src/llmq/quorums_chainlocks.h @@ -90,6 +90,9 @@ class CChainLocksHandler : public CRecoveredSigsListener void ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash); void AcceptedBlockHeader(const CBlockIndex* pindexNew); void UpdatedBlockTip(const CBlockIndex* pindexNew); + void TransactionAddedToMempool(const CTransactionRef& tx); + void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted); + void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected); void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); void CheckActiveState(); void TrySignChainTip(); From a61127e1ae289bcf07ecc0653225f8f59420be6b Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 13:52:30 +0200 Subject: [PATCH 113/987] Move filling of blockTxs into BlockConnected Also add code to remove entries in blockTxs when BlockDisconnected is called. --- src/llmq/quorums_chainlocks.cpp | 43 +++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index bcde11266593..e079fd4ba57a 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -352,12 +352,38 @@ void CChainLocksHandler::TransactionAddedToMempool(const CTransactionRef& tx) void CChainLocksHandler::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) { + if (!masternodeSync.IsBlockchainSynced()) { + return; + } + + // We listen for BlockConnected so that we can collect all TX ids of all included TXs of newly received blocks + // We need this information later when we try to sign a new tip, so that we can determine if all included TXs are + // safe. + + LOCK(cs); + + auto it = blockTxs.find(pindex->GetBlockHash()); + if (it == blockTxs.end()) { + // we must create this entry even if there are no lockable transactions in the block, so that TrySignChainTip + // later knows about this block + it = blockTxs.emplace(pindex->GetBlockHash(), std::make_shared>()).first; + } + auto& txids = *it->second; + + for (const auto& tx : pblock->vtx) { + if (tx->IsCoinBase() || tx->vin.empty()) { + continue; + } + + txids.emplace(tx->GetHash()); + } } void CChainLocksHandler::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) { - + LOCK(cs); + blockTxs.erase(pindexDisconnected->GetBlockHash()); } void CChainLocksHandler::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) @@ -377,21 +403,6 @@ void CChainLocksHandler::SyncTransaction(const CTransactionRef& tx, const CBlock int64_t curTime = GetAdjustedTime(); txFirstSeenTime.emplace(tx->GetHash(), curTime); } - - // We listen for SyncTransaction so that we can collect all TX ids of all included TXs of newly received blocks - // We need this information later when we try to sign a new tip, so that we can determine if all included TXs are - // safe. - if (pindex != nullptr && posInBlock != -1) { - auto it = blockTxs.find(pindex->GetBlockHash()); - if (it == blockTxs.end()) { - // we want this to be run even if handleTx == false, so that the coinbase TX triggers creation of an empty entry - it = blockTxs.emplace(pindex->GetBlockHash(), std::make_shared>()).first; - } - if (handleTx) { - auto& txs = *it->second; - txs.emplace(tx->GetHash()); - } - } } CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const uint256& blockHash) From 715a3e9518dedb1df095916ae63a5d68fc2b1064 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 13:56:04 +0200 Subject: [PATCH 114/987] Move updating of txFirstSeenTime into TransactionAddedToMempool and BlockConnected This removes the need for SyncTransaction --- src/llmq/quorums_chainlocks.cpp | 32 +++++++++++++------------------- src/llmq/quorums_chainlocks.h | 1 - 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index e079fd4ba57a..827730d72784 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -347,7 +347,17 @@ void CChainLocksHandler::TrySignChainTip() void CChainLocksHandler::TransactionAddedToMempool(const CTransactionRef& tx) { + if (tx->IsCoinBase() || tx->vin.empty()) { + return; + } + + if (!masternodeSync.IsBlockchainSynced()) { + return; + } + LOCK(cs); + int64_t curTime = GetAdjustedTime(); + txFirstSeenTime.emplace(tx->GetHash(), curTime); } void CChainLocksHandler::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) @@ -370,12 +380,15 @@ void CChainLocksHandler::BlockConnected(const std::shared_ptr& pbl } auto& txids = *it->second; + int64_t curTime = GetAdjustedTime(); + for (const auto& tx : pblock->vtx) { if (tx->IsCoinBase() || tx->vin.empty()) { continue; } txids.emplace(tx->GetHash()); + txFirstSeenTime.emplace(tx->GetHash(), curTime); } } @@ -386,25 +399,6 @@ void CChainLocksHandler::BlockDisconnected(const std::shared_ptr& blockTxs.erase(pindexDisconnected->GetBlockHash()); } -void CChainLocksHandler::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) -{ - if (!masternodeSync.IsBlockchainSynced()) { - return; - } - - bool handleTx = true; - if (tx->IsCoinBase() || tx->vin.empty()) { - handleTx = false; - } - - LOCK(cs); - - if (handleTx) { - int64_t curTime = GetAdjustedTime(); - txFirstSeenTime.emplace(tx->GetHash(), curTime); - } -} - CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const uint256& blockHash) { AssertLockNotHeld(cs); diff --git a/src/llmq/quorums_chainlocks.h b/src/llmq/quorums_chainlocks.h index 684a4b838520..36308b28e0a0 100644 --- a/src/llmq/quorums_chainlocks.h +++ b/src/llmq/quorums_chainlocks.h @@ -93,7 +93,6 @@ class CChainLocksHandler : public CRecoveredSigsListener void TransactionAddedToMempool(const CTransactionRef& tx); void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted); void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected); - void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); void CheckActiveState(); void TrySignChainTip(); void EnforceBestChainLock(); From 816efa9cd41ee8767f277a078d77727eaa2d92ce Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 16:13:59 +0200 Subject: [PATCH 115/987] Add missing directories to CMakeLists.txt and sort the list --- CMakeLists.txt | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fff48643e30..962bf77ead40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,28 +37,40 @@ add_definitions( ) file(GLOB SOURCE_FILES + src/*.cpp + src/*.h src/bench/*.cpp src/bench/*.h src/bls/*.cpp src/bls/*.h src/compat/*.cpp src/compat/*.h - src/consensus/*.h src/consensus/*.cpp + src/consensus/*.h src/crypto/*.c - src/crypto/*.h src/crypto/*.cpp + src/crypto/*.h + src/evo/*.cpp + src/evo/*.h src/leveldb/db/*.cc src/leveldb/db/*.h src/leveldb/include/*.h + src/llmq/*.cpp + src/llmq/*.h + src/masternode/*.cpp + src/masternode/*.h src/policy/*.cpp src/policy/*.h src/primitives/*.cpp src/primitives/*.h - src/qt/test/*.cpp - src/qt/test/*.h + src/privatesend/*.cpp + src/privatesend/*.h src/qt/*.cpp src/qt/*.h + src/qt/test/*.cpp + src/qt/test/*.h + src/rpc/*.cpp + src/rpc/*.h src/script/*.cpp src/script/*.h src/secp256k1/include/*.h @@ -67,19 +79,11 @@ file(GLOB SOURCE_FILES src/univalue/include/*.h src/univalue/lib/*.cpp src/univalue/lib/*.h - src/wallet/test/*.cpp src/wallet/*.cpp src/wallet/*.h + src/wallet/test/*.cpp src/zmq/*.cpp src/zmq/*.h - src/*.cpp - src/*.h - src/evo/*.h - src/evo/*.cpp - src/llmq/*.h - src/llmq/*.cpp - src/rpc/*.cpp - src/rpc/*.h ) add_executable(dash ${SOURCE_FILES}) From 8df25bbfe4f5c7e22a483235bef604f1b90a6191 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 16:22:09 +0200 Subject: [PATCH 116/987] Call and implemente new signals in CPrivateSend Instead of relying on CDSNotificationInterface running compatibility code. This also removes locking of cs_main, as this seemed to be not needed. --- src/dsnotificationinterface.cpp | 4 +++- src/privatesend/privatesend.cpp | 37 ++++++++++++++++++++++++++------- src/privatesend/privatesend.h | 7 ++++++- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 233961a469ce..fcaa04d724db 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -75,13 +75,13 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con void CDSNotificationInterface::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { instantsend.SyncTransaction(tx, pindex, posInBlock); - CPrivateSend::SyncTransaction(tx, pindex, posInBlock); } void CDSNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx) { llmq::quorumInstantSendManager->TransactionAddedToMempool(ptx); llmq::chainLocksHandler->TransactionAddedToMempool(ptx); + CPrivateSend::TransactionAddedToMempool(ptx); SyncTransaction(ptx); } @@ -97,6 +97,7 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptrBlockConnected(pblock, pindex, vtxConflicted); llmq::chainLocksHandler->BlockConnected(pblock, pindex, vtxConflicted); + CPrivateSend::BlockConnected(pblock, pindex, vtxConflicted); for (const CTransactionRef& ptx : vtxConflicted) { SyncTransaction(ptx); @@ -110,6 +111,7 @@ void CDSNotificationInterface::BlockDisconnected(const std::shared_ptrBlockDisconnected(pblock, pindexDisconnected); llmq::chainLocksHandler->BlockDisconnected(pblock, pindexDisconnected); + CPrivateSend::BlockDisconnected(pblock, pindexDisconnected); for (const CTransactionRef& ptx : pblock->vtx) { SyncTransaction(ptx, pindexDisconnected->pprev, -1); diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 8a7b9ffc01a8..ad7da6954718 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -509,16 +509,39 @@ void CPrivateSend::UpdatedBlockTip(const CBlockIndex* pindex) } } -void CPrivateSend::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) +void CPrivateSend::UpdateDSTXConfirmedHeight(const CTransactionRef& tx, int nHeight) { - if (tx->IsCoinBase()) return; - - LOCK2(cs_main, cs_mapdstx); + AssertLockHeld(cs_mapdstx); uint256 txHash = tx->GetHash(); if (!mapDSTX.count(txHash)) return; - // When tx is 0-confirmed or conflicted, posInBlock is SYNC_TRANSACTION_NOT_IN_BLOCK and nConfirmedHeight should be set to -1 - mapDSTX[txHash].SetConfirmedHeight((posInBlock == -1 || pindex == nullptr) ? -1 : pindex->nHeight); - LogPrint(BCLog::PRIVATESEND, "CPrivateSend::SyncTransaction -- txid=%s\n", txHash.ToString()); + mapDSTX[txHash].SetConfirmedHeight(nHeight); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::%s -- txid=%s, nHeight=%d\n", __func__, txHash.ToString(), nHeight); +} + +void CPrivateSend::TransactionAddedToMempool(const CTransactionRef& tx) +{ + LOCK(cs_mapdstx); + UpdateDSTXConfirmedHeight(tx, -1); +} + +void CPrivateSend::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) +{ + LOCK(cs_mapdstx); + for (const auto& tx : vtxConflicted) { + UpdateDSTXConfirmedHeight(tx, -1); + } + + for (const auto& tx : pblock->vtx) { + UpdateDSTXConfirmedHeight(tx, pindex->nHeight); + } +} + +void CPrivateSend::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) +{ + LOCK(cs_mapdstx); + for (const auto& tx : pblock->vtx) { + UpdateDSTXConfirmedHeight(tx, -1); + } } diff --git a/src/privatesend/privatesend.h b/src/privatesend/privatesend.h index 4ff8562779f1..0a0534b44947 100644 --- a/src/privatesend/privatesend.h +++ b/src/privatesend/privatesend.h @@ -422,7 +422,12 @@ class CPrivateSend static CPrivateSendBroadcastTx GetDSTX(const uint256& hash); static void UpdatedBlockTip(const CBlockIndex* pindex); - static void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); + + static void UpdateDSTXConfirmedHeight(const CTransactionRef& tx, int nHeight); + static void TransactionAddedToMempool(const CTransactionRef& tx); + static void BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted); + static void BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected); + }; #endif From 617c4a4cc0fb960e2c727db9a3f0f79f8aa879d9 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 16:23:19 +0200 Subject: [PATCH 117/987] Use mapDSTX.find() instead of count() and [] --- src/privatesend/privatesend.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index ad7da6954718..1dd015f857f9 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -513,11 +513,13 @@ void CPrivateSend::UpdateDSTXConfirmedHeight(const CTransactionRef& tx, int nHei { AssertLockHeld(cs_mapdstx); - uint256 txHash = tx->GetHash(); - if (!mapDSTX.count(txHash)) return; + auto it = mapDSTX.find(tx->GetHash()); + if (it == mapDSTX.end()) { + return; + } - mapDSTX[txHash].SetConfirmedHeight(nHeight); - LogPrint(BCLog::PRIVATESEND, "CPrivateSend::%s -- txid=%s, nHeight=%d\n", __func__, txHash.ToString(), nHeight); + it->second.SetConfirmedHeight(nHeight); + LogPrint(BCLog::PRIVATESEND, "CPrivateSend::%s -- txid=%s, nHeight=%d\n", __func__, tx->GetHash().ToString(), nHeight); } void CPrivateSend::TransactionAddedToMempool(const CTransactionRef& tx) From 8675a5064d1fc431f34e4e3ecba3c80da625d063 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 27 May 2019 16:24:34 +0200 Subject: [PATCH 118/987] Add TODO comment about need to remove compatibility code --- src/dsnotificationinterface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index fcaa04d724db..f957a25b7556 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -74,6 +74,7 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con void CDSNotificationInterface::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) { + // TODO when the old InstantSend system is removed, also remove this whole method and all the surrounding compatiblity code instantsend.SyncTransaction(tx, pindex, posInBlock); } From f8c5a14f3d925a555650f14feb3302a4d56bd150 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 20 Apr 2017 21:16:19 +0200 Subject: [PATCH 119/987] Merge #9942: Refactor CBlockPolicyEstimator 68af651 MOVEONLY: move TxConfirmStats to cpp (Alex Morcos) 2332f19 Initialize TxConfirmStats in constructor (Alex Morcos) 5ba81e5 Read and Write fee estimate file directly from CBlockPolicyEstimator (Alex Morcos) 14e10aa Call estimate(Smart)Fee directly from CBlockPolicyEstimator (Alex Morcos) dbb9e36 Give CBlockPolicyEstimator it's own lock (Alex Morcos) f6187d6 Make processBlockTx private. (Alex Morcos) ae7327b Make feeEstimator its own global instance of CBlockPolicyEstimator (Alex Morcos) Tree-SHA512: dbf3bd2b30822e609a35f3da519b62d23f8a50e564750695ddebd08553b4c01874ae3e07d792c6cc78cc377d2db33b951ffedc46ac7edaf5793f9ebb931713af finish #9942 by removing removed functions Signed-off-by: Pasta --- src/init.cpp | 5 +- src/policy/fees.cpp | 209 ++++++++++++++++++++++++----- src/policy/fees.h | 129 ++---------------- src/qt/coincontroldialog.cpp | 5 +- src/qt/sendcoinsdialog.cpp | 3 +- src/rpc/mining.cpp | 5 +- src/test/policyestimator_tests.cpp | 45 ++++--- src/txmempool.cpp | 64 +-------- src/txmempool.h | 16 +-- src/validation.cpp | 3 +- src/validation.h | 2 + src/wallet/rpcwallet.cpp | 1 + src/wallet/wallet.cpp | 11 +- src/wallet/wallet.h | 5 +- 14 files changed, 244 insertions(+), 259 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 292258d1133d..43563935f8b5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -26,6 +26,7 @@ #include "netbase.h" #include "net.h" #include "net_processing.h" +#include "policy/fees.h" #include "policy/policy.h" #include "rpc/server.h" #include "rpc/register.h" @@ -287,7 +288,7 @@ void PrepareShutdown() boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; CAutoFile est_fileout(fopen(est_path.string().c_str(), "wb"), SER_DISK, CLIENT_VERSION); if (!est_fileout.IsNull()) - mempool.WriteFeeEstimates(est_fileout); + ::feeEstimator.Write(est_fileout); else LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string()); fFeeEstimatesInitialized = false; @@ -1926,7 +1927,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION); // Allowed to fail as this file IS missing on first startup. if (!est_filein.IsNull()) - mempool.ReadFeeEstimates(est_filein); + ::feeEstimator.Read(est_filein); fFeeEstimatesInitialized = true; // ********************************************************* Step 8: load wallet diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 75e3ce5d0ccb..315509ce03d1 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -7,13 +7,120 @@ #include "policy/policy.h" #include "amount.h" +#include "clientversion.h" #include "primitives/transaction.h" #include "streams.h" #include "txmempool.h" #include "util.h" -void TxConfirmStats::Initialize(std::vector& defaultBuckets, - unsigned int maxConfirms, double _decay) +/** + * We will instantiate an instance of this class to track transactions that were + * included in a block. We will lump transactions into a bucket according to their + * approximate feerate and then track how long it took for those txs to be included in a block + * + * The tracking of unconfirmed (mempool) transactions is completely independent of the + * historical tracking of transactions that have been confirmed in a block. + */ +class TxConfirmStats +{ +private: + //Define the buckets we will group transactions into + std::vector buckets; // The upper-bound of the range for the bucket (inclusive) + std::map bucketMap; // Map of bucket upper-bound to index into all vectors by bucket + + // For each bucket X: + // Count the total # of txs in each bucket + // Track the historical moving average of this total over blocks + std::vector txCtAvg; + // and calculate the total for the current block to update the moving average + std::vector curBlockTxCt; + + // Count the total # of txs confirmed within Y blocks in each bucket + // Track the historical moving average of theses totals over blocks + std::vector > confAvg; // confAvg[Y][X] + // and calculate the totals for the current block to update the moving averages + std::vector > curBlockConf; // curBlockConf[Y][X] + + // Sum the total feerate of all tx's in each bucket + // Track the historical moving average of this total over blocks + std::vector avg; + // and calculate the total for the current block to update the moving average + std::vector curBlockVal; + + // Combine the conf counts with tx counts to calculate the confirmation % for each Y,X + // Combine the total value with the tx counts to calculate the avg feerate per bucket + + double decay; + + // Mempool counts of outstanding transactions + // For each bucket X, track the number of transactions in the mempool + // that are unconfirmed for each possible confirmation value Y + std::vector > unconfTxs; //unconfTxs[Y][X] + // transactions still unconfirmed after MAX_CONFIRMS for each bucket + std::vector oldUnconfTxs; + +public: + /** + * Create new TxConfirmStats. This is called by BlockPolicyEstimator's + * constructor with default values. + * @param defaultBuckets contains the upper limits for the bucket boundaries + * @param maxConfirms max number of confirms to track + * @param decay how much to decay the historical moving average per block + */ + TxConfirmStats(const std::vector& defaultBuckets, unsigned int maxConfirms, double decay); + + /** Clear the state of the curBlock variables to start counting for the new block */ + void ClearCurrent(unsigned int nBlockHeight); + + /** + * Record a new transaction data point in the current block stats + * @param blocksToConfirm the number of blocks it took this transaction to confirm + * @param val the feerate of the transaction + * @warning blocksToConfirm is 1-based and has to be >= 1 + */ + void Record(int blocksToConfirm, double val); + + /** Record a new transaction entering the mempool*/ + unsigned int NewTx(unsigned int nBlockHeight, double val); + + /** Remove a transaction from mempool tracking stats*/ + void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, + unsigned int bucketIndex); + + /** Update our estimates by decaying our historical moving average and updating + with the data gathered from the current block */ + void UpdateMovingAverages(); + + /** + * Calculate a feerate estimate. Find the lowest value bucket (or range of buckets + * to make sure we have enough data points) whose transactions still have sufficient likelihood + * of being confirmed within the target number of confirmations + * @param confTarget target number of confirmations + * @param sufficientTxVal required average number of transactions per block in a bucket range + * @param minSuccess the success probability we require + * @param requireGreater return the lowest feerate such that all higher values pass minSuccess OR + * return the highest feerate such that all lower values fail minSuccess + * @param nBlockHeight the current block height + */ + double EstimateMedianVal(int confTarget, double sufficientTxVal, + double minSuccess, bool requireGreater, unsigned int nBlockHeight) const; + + /** Return the max number of confirms we're tracking */ + unsigned int GetMaxConfirms() const { return confAvg.size(); } + + /** Write state of estimation data to a file*/ + void Write(CAutoFile& fileout) const; + + /** + * Read saved state of estimation data from a file and replace all internal data structures and + * variables with this state. + */ + void Read(CAutoFile& filein); +}; + + +TxConfirmStats::TxConfirmStats(const std::vector& defaultBuckets, + unsigned int maxConfirms, double _decay) { decay = _decay; for (unsigned int i = 0; i < defaultBuckets.size(); i++) { @@ -76,7 +183,7 @@ void TxConfirmStats::UpdateMovingAverages() // returns -1 on error conditions double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal, double successBreakPoint, bool requireGreater, - unsigned int nBlockHeight) + unsigned int nBlockHeight) const { // Counters for a bucket (or range of buckets) double nConf = 0; // Number of tx's confirmed within the confTarget @@ -172,7 +279,7 @@ double TxConfirmStats::EstimateMedianVal(int confTarget, double sufficientTxVal, return median; } -void TxConfirmStats::Write(CAutoFile& fileout) +void TxConfirmStats::Write(CAutoFile& fileout) const { fileout << decay; fileout << buckets; @@ -289,9 +396,10 @@ void TxConfirmStats::removeTx(unsigned int entryHeight, unsigned int nBestSeenHe // of no harm to try to remove them again. bool CBlockPolicyEstimator::removeTx(uint256 hash) { + LOCK(cs_feeEstimator); std::map::iterator pos = mapMemPoolTxs.find(hash); if (pos != mapMemPoolTxs.end()) { - feeStats.removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex); + feeStats->removeTx(pos->second.blockHeight, nBestSeenHeight, pos->second.bucketIndex); mapMemPoolTxs.erase(hash); return true; } else { @@ -309,11 +417,17 @@ CBlockPolicyEstimator::CBlockPolicyEstimator() vfeelist.push_back(bucketBoundary); } vfeelist.push_back(INF_FEERATE); - feeStats.Initialize(vfeelist, MAX_BLOCK_CONFIRMS, DEFAULT_DECAY); + feeStats = new TxConfirmStats(vfeelist, MAX_BLOCK_CONFIRMS, DEFAULT_DECAY); +} + +CBlockPolicyEstimator::~CBlockPolicyEstimator() +{ + delete feeStats; } void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, bool validFeeEstimate) { + LOCK(cs_feeEstimator); unsigned int txHeight = entry.GetHeight(); uint256 hash = entry.GetTx().GetHash(); if (mapMemPoolTxs.count(hash)) { @@ -341,7 +455,7 @@ void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, boo CFeeRate feeRate(entry.GetFee(), entry.GetTxSize()); mapMemPoolTxs[hash].blockHeight = txHeight; - mapMemPoolTxs[hash].bucketIndex = feeStats.NewTx(txHeight, (double)feeRate.GetFeePerK()); + mapMemPoolTxs[hash].bucketIndex = feeStats->NewTx(txHeight, (double)feeRate.GetFeePerK()); } bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry* entry) @@ -365,13 +479,14 @@ bool CBlockPolicyEstimator::processBlockTx(unsigned int nBlockHeight, const CTxM // Feerates are stored and reported as BTC-per-kb: CFeeRate feeRate(entry->GetFee(), entry->GetTxSize()); - feeStats.Record(blocksToConfirm, (double)feeRate.GetFeePerK()); + feeStats->Record(blocksToConfirm, (double)feeRate.GetFeePerK()); return true; } void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight, std::vector& entries) { + LOCK(cs_feeEstimator); if (nBlockHeight <= nBestSeenHeight) { // Ignore side chains and re-orgs; assuming they are random // they don't affect the estimate. @@ -387,7 +502,7 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight, nBestSeenHeight = nBlockHeight; // Clear the current block state and update unconfirmed circular buffer - feeStats.ClearCurrent(nBlockHeight); + feeStats->ClearCurrent(nBlockHeight); unsigned int countedTxs = 0; // Repopulate the current block states @@ -397,7 +512,7 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight, } // Update all exponential averages with the current block state - feeStats.UpdateMovingAverages(); + feeStats->UpdateMovingAverages(); LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy after updating estimates for %u of %u txs in block, since last block %u of %u tracked, new mempool map size %u\n", countedTxs, entries.size(), trackedTxs, trackedTxs + untrackedTxs, mapMemPoolTxs.size()); @@ -406,14 +521,15 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight, untrackedTxs = 0; } -CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget) +CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget) const { + LOCK(cs_feeEstimator); // Return failure if trying to analyze a target we're not tracking // It's not possible to get reasonable estimates for confTarget of 1 - if (confTarget <= 1 || (unsigned int)confTarget > feeStats.GetMaxConfirms()) + if (confTarget <= 1 || (unsigned int)confTarget > feeStats->GetMaxConfirms()) return CFeeRate(0); - double median = feeStats.EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); + double median = feeStats->EstimateMedianVal(confTarget, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); if (median < 0) return CFeeRate(0); @@ -421,22 +537,28 @@ CFeeRate CBlockPolicyEstimator::estimateFee(int confTarget) return CFeeRate(median); } -CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool) +CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool) const { if (answerFoundAtTarget) *answerFoundAtTarget = confTarget; - // Return failure if trying to analyze a target we're not tracking - if (confTarget <= 0 || (unsigned int)confTarget > feeStats.GetMaxConfirms()) - return CFeeRate(0); - - // It's not possible to get reasonable estimates for confTarget of 1 - if (confTarget == 1) - confTarget = 2; double median = -1; - while (median < 0 && (unsigned int)confTarget <= feeStats.GetMaxConfirms()) { - median = feeStats.EstimateMedianVal(confTarget++, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); - } + + { + LOCK(cs_feeEstimator); + + // Return failure if trying to analyze a target we're not tracking + if (confTarget <= 0 || (unsigned int)confTarget > feeStats->GetMaxConfirms()) + return CFeeRate(0); + + // It's not possible to get reasonable estimates for confTarget of 1 + if (confTarget == 1) + confTarget = 2; + + while (median < 0 && (unsigned int)confTarget <= feeStats->GetMaxConfirms()) { + median = feeStats->EstimateMedianVal(confTarget++, SUFFICIENT_FEETXS, MIN_SUCCESS_PCT, true, nBestSeenHeight); + } + } // Must unlock cs_feeEstimator before taking mempool locks if (answerFoundAtTarget) *answerFoundAtTarget = confTarget - 1; @@ -452,18 +574,39 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun return CFeeRate(median); } -void CBlockPolicyEstimator::Write(CAutoFile& fileout) +bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const { - fileout << nBestSeenHeight; - feeStats.Write(fileout); + try { + LOCK(cs_feeEstimator); + fileout << 139900; // version required to read: 0.13.99 or later + fileout << CLIENT_VERSION; // version that wrote the file + fileout << nBestSeenHeight; + feeStats->Write(fileout); + } + catch (const std::exception&) { + LogPrintf("CBlockPolicyEstimator::Write(): unable to read policy estimator data (non-fatal)\n"); + return false; + } + return true; } -void CBlockPolicyEstimator::Read(CAutoFile& filein, int nFileVersion) +bool CBlockPolicyEstimator::Read(CAutoFile& filein) { - int nFileBestSeenHeight; - filein >> nFileBestSeenHeight; - feeStats.Read(filein); - nBestSeenHeight = nFileBestSeenHeight; - // if nVersionThatWrote < 120300 then another TxConfirmStats (for priority) follows but can be ignored. + try { + LOCK(cs_feeEstimator); + int nVersionRequired, nVersionThatWrote, nFileBestSeenHeight; + filein >> nVersionRequired >> nVersionThatWrote; + if (nVersionRequired > CLIENT_VERSION) + return error("CBlockPolicyEstimator::Read(): up-version (%d) fee estimate file", nVersionRequired); + filein >> nFileBestSeenHeight; + feeStats->Read(filein); + nBestSeenHeight = nFileBestSeenHeight; + // if nVersionThatWrote < 120300 then another TxConfirmStats (for priority) follows but can be ignored. + } + catch (const std::exception&) { + LogPrintf("CBlockPolicyEstimator::Read(): unable to read policy estimator data (non-fatal)\n"); + return false; + } + return true; } diff --git a/src/policy/fees.h b/src/policy/fees.h index 06494cabc7f0..f59f35a273e1 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -8,6 +8,7 @@ #include "amount.h" #include "uint256.h" #include "random.h" +#include "sync.h" #include #include @@ -17,6 +18,7 @@ class CAutoFile; class CFeeRate; class CTxMemPoolEntry; class CTxMemPool; +class TxConfirmStats; /** \class CBlockPolicyEstimator * The BlockPolicyEstimator is used for estimating the feerate needed @@ -59,113 +61,6 @@ class CTxMemPool; * they've been outstanding. */ -/** - * We will instantiate an instance of this class to track transactions that were - * included in a block. We will lump transactions into a bucket according to their - * approximate feerate and then track how long it took for those txs to be included in a block - * - * The tracking of unconfirmed (mempool) transactions is completely independent of the - * historical tracking of transactions that have been confirmed in a block. - */ -class TxConfirmStats -{ -private: - //Define the buckets we will group transactions into - std::vector buckets; // The upper-bound of the range for the bucket (inclusive) - std::map bucketMap; // Map of bucket upper-bound to index into all vectors by bucket - - // For each bucket X: - // Count the total # of txs in each bucket - // Track the historical moving average of this total over blocks - std::vector txCtAvg; - // and calculate the total for the current block to update the moving average - std::vector curBlockTxCt; - - // Count the total # of txs confirmed within Y blocks in each bucket - // Track the historical moving average of theses totals over blocks - std::vector > confAvg; // confAvg[Y][X] - // and calculate the totals for the current block to update the moving averages - std::vector > curBlockConf; // curBlockConf[Y][X] - - // Sum the total feerate of all tx's in each bucket - // Track the historical moving average of this total over blocks - std::vector avg; - // and calculate the total for the current block to update the moving average - std::vector curBlockVal; - - // Combine the conf counts with tx counts to calculate the confirmation % for each Y,X - // Combine the total value with the tx counts to calculate the avg feerate per bucket - - double decay; - - // Mempool counts of outstanding transactions - // For each bucket X, track the number of transactions in the mempool - // that are unconfirmed for each possible confirmation value Y - std::vector > unconfTxs; //unconfTxs[Y][X] - // transactions still unconfirmed after MAX_CONFIRMS for each bucket - std::vector oldUnconfTxs; - -public: - /** - * Initialize the data structures. This is called by BlockPolicyEstimator's - * constructor with default values. - * @param defaultBuckets contains the upper limits for the bucket boundaries - * @param maxConfirms max number of confirms to track - * @param decay how much to decay the historical moving average per block - */ - void Initialize(std::vector& defaultBuckets, unsigned int maxConfirms, double decay); - - /** Clear the state of the curBlock variables to start counting for the new block */ - void ClearCurrent(unsigned int nBlockHeight); - - /** - * Record a new transaction data point in the current block stats - * @param blocksToConfirm the number of blocks it took this transaction to confirm - * @param val the feerate of the transaction - * @warning blocksToConfirm is 1-based and has to be >= 1 - */ - void Record(int blocksToConfirm, double val); - - /** Record a new transaction entering the mempool*/ - unsigned int NewTx(unsigned int nBlockHeight, double val); - - /** Remove a transaction from mempool tracking stats*/ - void removeTx(unsigned int entryHeight, unsigned int nBestSeenHeight, - unsigned int bucketIndex); - - /** Update our estimates by decaying our historical moving average and updating - with the data gathered from the current block */ - void UpdateMovingAverages(); - - /** - * Calculate a feerate estimate. Find the lowest value bucket (or range of buckets - * to make sure we have enough data points) whose transactions still have sufficient likelihood - * of being confirmed within the target number of confirmations - * @param confTarget target number of confirmations - * @param sufficientTxVal required average number of transactions per block in a bucket range - * @param minSuccess the success probability we require - * @param requireGreater return the lowest feerate such that all higher values pass minSuccess OR - * return the highest feerate such that all lower values fail minSuccess - * @param nBlockHeight the current block height - */ - double EstimateMedianVal(int confTarget, double sufficientTxVal, - double minSuccess, bool requireGreater, unsigned int nBlockHeight); - - /** Return the max number of confirms we're tracking */ - unsigned int GetMaxConfirms() { return confAvg.size(); } - - /** Write state of estimation data to a file*/ - void Write(CAutoFile& fileout); - - /** - * Read saved state of estimation data from a file and replace all internal data structures and - * variables with this state. - */ - void Read(CAutoFile& filein); -}; - - - /** Track confirm delays up to 25 blocks, can't estimate beyond that */ static const unsigned int MAX_BLOCK_CONFIRMS = 25; @@ -204,14 +99,12 @@ class CBlockPolicyEstimator public: /** Create new BlockPolicyEstimator and initialize stats tracking classes with default values */ CBlockPolicyEstimator(); + ~CBlockPolicyEstimator(); /** Process all the transactions that have been included in a block */ void processBlock(unsigned int nBlockHeight, std::vector& entries); - /** Process a transaction confirmed in a block*/ - bool processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry* entry); - /** Process a transaction accepted to the mempool*/ void processTransaction(const CTxMemPoolEntry& entry, bool validFeeEstimate); @@ -219,19 +112,19 @@ class CBlockPolicyEstimator bool removeTx(uint256 hash); /** Return a feerate estimate */ - CFeeRate estimateFee(int confTarget); + CFeeRate estimateFee(int confTarget) const; /** Estimate feerate needed to get be included in a block within * confTarget blocks. If no answer can be given at confTarget, return an * estimate at the lowest target where one can be given. */ - CFeeRate estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool); + CFeeRate estimateSmartFee(int confTarget, int *answerFoundAtTarget, const CTxMemPool& pool) const; /** Write estimation data to a file */ - void Write(CAutoFile& fileout); + bool Write(CAutoFile& fileout) const; /** Read estimation data from a file */ - void Read(CAutoFile& filein, int nFileVersion); + bool Read(CAutoFile& filein); private: CFeeRate minTrackedFee; //!< Passed to constructor to avoid dependency on main @@ -247,9 +140,15 @@ class CBlockPolicyEstimator std::map mapMemPoolTxs; /** Classes to track historical data on transaction confirmations */ - TxConfirmStats feeStats; + TxConfirmStats* feeStats; unsigned int trackedTxs; unsigned int untrackedTxs; + + mutable CCriticalSection cs_feeEstimator; + + /** Process a transaction confirmed in a block*/ + bool processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry* entry); + }; #endif /*BITCOIN_POLICYESTIMATOR_H */ diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 9ab17d030661..01a31f056b0d 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -16,6 +16,7 @@ #include "wallet/coincontrol.h" #include "init.h" +#include "policy/fees.h" #include "policy/policy.h" #include "validation.h" // For mempool #include "wallet/wallet.h" @@ -556,7 +557,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytes -= 34; // Fee - nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); + nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, ::mempool, ::feeEstimator); if (nPayFee > 0 && coinControl->nMinimumTotalFee > nPayFee) nPayFee = coinControl->nMinimumTotalFee; @@ -645,7 +646,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) if (payTxFee.GetFeePerK() > 0) dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000; else { - dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), mempool.estimateSmartFee(nTxConfirmTarget).GetFeePerK()) / 1000; + dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(nTxConfirmTarget, NULL, ::mempool).GetFeePerK()) / 1000; } QString toolTip4 = tr("Can vary +/- %1 duff(s) per input.").arg(dFeeVary); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 091b4c3afcd0..82661e059df8 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -21,6 +21,7 @@ #include "validation.h" // mempool and minRelayTxFee #include "ui_interface.h" #include "txmempool.h" +#include "policy/fees.h" #include "wallet/wallet.h" #include "privatesend/privatesend.h" @@ -760,7 +761,7 @@ void SendCoinsDialog::updateSmartFeeLabel() int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; int estimateFoundAtBlocks = nBlocksToConfirm; - CFeeRate feeRate = mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks); + CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks, ::mempool); if (feeRate <= CFeeRate(0)) // not enough data => minfee { ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 1f10cbd5efa6..43558f698606 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -16,6 +16,7 @@ #include "validation.h" #include "miner.h" #include "net.h" +#include "policy/fees.h" #include "pow.h" #include "rpc/blockchain.h" #include "rpc/server.h" @@ -852,7 +853,7 @@ UniValue estimatefee(const JSONRPCRequest& request) if (nBlocks < 1) nBlocks = 1; - CFeeRate feeRate = mempool.estimateFee(nBlocks); + CFeeRate feeRate = ::feeEstimator.estimateFee(nBlocks); if (feeRate == CFeeRate(0)) return -1.0; @@ -889,7 +890,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) UniValue result(UniValue::VOBJ); int answerFound; - CFeeRate feeRate = mempool.estimateSmartFee(nBlocks, &answerFound); + CFeeRate feeRate = ::feeEstimator.estimateSmartFee(nBlocks, &answerFound, ::mempool); result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK()))); result.push_back(Pair("blocks", answerFound)); return result; diff --git a/src/test/policyestimator_tests.cpp b/src/test/policyestimator_tests.cpp index 4b5bccb94283..1eea585ac3ad 100644 --- a/src/test/policyestimator_tests.cpp +++ b/src/test/policyestimator_tests.cpp @@ -15,7 +15,8 @@ BOOST_FIXTURE_TEST_SUITE(policyestimator_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) { - CTxMemPool mpool; + CBlockPolicyEstimator feeEst; + CTxMemPool mpool(&feeEst); TestMemPoolEntryHelper entry; CAmount basefee(2000); CAmount deltaFee(100); @@ -77,16 +78,16 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) // At this point we should need to combine 5 buckets to get enough data points // So estimateFee(1,2,3) should fail and estimateFee(4) should return somewhere around // 8*baserate. estimateFee(4) %'s are 100,100,100,100,90 = average 98% - BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0)); - BOOST_CHECK(mpool.estimateFee(2) == CFeeRate(0)); - BOOST_CHECK(mpool.estimateFee(3) == CFeeRate(0)); - BOOST_CHECK(mpool.estimateFee(4).GetFeePerK() < 8*baseRate.GetFeePerK() + deltaFee); - BOOST_CHECK(mpool.estimateFee(4).GetFeePerK() > 8*baseRate.GetFeePerK() - deltaFee); + BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0)); + BOOST_CHECK(feeEst.estimateFee(2) == CFeeRate(0)); + BOOST_CHECK(feeEst.estimateFee(3) == CFeeRate(0)); + BOOST_CHECK(feeEst.estimateFee(4).GetFeePerK() < 8*baseRate.GetFeePerK() + deltaFee); + BOOST_CHECK(feeEst.estimateFee(4).GetFeePerK() > 8*baseRate.GetFeePerK() - deltaFee); int answerFound; - BOOST_CHECK(mpool.estimateSmartFee(1, &answerFound) == mpool.estimateFee(4) && answerFound == 4); - BOOST_CHECK(mpool.estimateSmartFee(3, &answerFound) == mpool.estimateFee(4) && answerFound == 4); - BOOST_CHECK(mpool.estimateSmartFee(4, &answerFound) == mpool.estimateFee(4) && answerFound == 4); - BOOST_CHECK(mpool.estimateSmartFee(8, &answerFound) == mpool.estimateFee(8) && answerFound == 8); + BOOST_CHECK(feeEst.estimateSmartFee(1, &answerFound, mpool) == feeEst.estimateFee(4) && answerFound == 4); + BOOST_CHECK(feeEst.estimateSmartFee(3, &answerFound, mpool) == feeEst.estimateFee(4) && answerFound == 4); + BOOST_CHECK(feeEst.estimateSmartFee(4, &answerFound, mpool) == feeEst.estimateFee(4) && answerFound == 4); + BOOST_CHECK(feeEst.estimateSmartFee(8, &answerFound, mpool) == feeEst.estimateFee(8) && answerFound == 8); } } @@ -98,7 +99,7 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) // Second highest feerate has 100% chance of being included by 2 blocks, // so estimateFee(2) should return 9*baseRate etc... for (int i = 1; i < 10;i++) { - origFeeEst.push_back(mpool.estimateFee(i).GetFeePerK()); + origFeeEst.push_back(feeEst.estimateFee(i).GetFeePerK()); if (i > 2) { // Fee estimates should be monotonically decreasing BOOST_CHECK(origFeeEst[i-1] <= origFeeEst[i-2]); } @@ -117,10 +118,10 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) while (blocknum < 250) mpool.removeForBlock(block, ++blocknum); - BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0)); + BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0)); for (int i = 2; i < 10;i++) { - BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee); - BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); + BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] + deltaFee); + BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); } @@ -140,8 +141,8 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) int answerFound; for (int i = 1; i < 10;i++) { - BOOST_CHECK(mpool.estimateFee(i) == CFeeRate(0) || mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); - BOOST_CHECK(mpool.estimateSmartFee(i, &answerFound).GetFeePerK() > origFeeEst[answerFound-1] - deltaFee); + BOOST_CHECK(feeEst.estimateFee(i) == CFeeRate(0) || feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); + BOOST_CHECK(feeEst.estimateSmartFee(i, &answerFound, mpool).GetFeePerK() > origFeeEst[answerFound-1] - deltaFee); } // Mine all those transactions @@ -156,9 +157,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) } mpool.removeForBlock(block, 265); block.clear(); - BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0)); + BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0)); for (int i = 2; i < 10;i++) { - BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); + BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() > origFeeEst[i-1] - deltaFee); } // Mine 200 more blocks where everything is mined every block @@ -178,9 +179,9 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) mpool.removeForBlock(block, ++blocknum); block.clear(); } - BOOST_CHECK(mpool.estimateFee(1) == CFeeRate(0)); + BOOST_CHECK(feeEst.estimateFee(1) == CFeeRate(0)); for (int i = 2; i < 10; i++) { - BOOST_CHECK(mpool.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee); + BOOST_CHECK(feeEst.estimateFee(i).GetFeePerK() < origFeeEst[i-1] - deltaFee); } // Test that if the mempool is limited, estimateSmartFee won't return a value below the mempool min fee @@ -189,8 +190,8 @@ BOOST_AUTO_TEST_CASE(BlockPolicyEstimates) mpool.TrimToSize(1); BOOST_CHECK(mpool.GetMinFee(1).GetFeePerK() > feeV[5]); for (int i = 1; i < 10; i++) { - BOOST_CHECK(mpool.estimateSmartFee(i).GetFeePerK() >= mpool.estimateFee(i).GetFeePerK()); - BOOST_CHECK(mpool.estimateSmartFee(i).GetFeePerK() >= mpool.GetMinFee(1).GetFeePerK()); + BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool).GetFeePerK() >= feeEst.estimateFee(i).GetFeePerK()); + BOOST_CHECK(feeEst.estimateSmartFee(i, NULL, mpool).GetFeePerK() >= mpool.GetMinFee(1).GetFeePerK()); } } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 49c071e87280..a293915bf19a 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -5,7 +5,6 @@ #include "txmempool.h" -#include "clientversion.h" #include "consensus/consensus.h" #include "consensus/validation.h" #include "instantsend.h" @@ -18,7 +17,6 @@ #include "util.h" #include "utilmoneystr.h" #include "utiltime.h" -#include "version.h" #include "hash.h" #include "evo/specialtx.h" @@ -336,8 +334,8 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, assert(int(nSigOpCountWithAncestors) >= 0); } -CTxMemPool::CTxMemPool() : - nTransactionsUpdated(0) +CTxMemPool::CTxMemPool(CBlockPolicyEstimator* estimator) : + nTransactionsUpdated(0), minerPolicyEstimator(estimator) { _clear(); //lock free clear @@ -345,13 +343,6 @@ CTxMemPool::CTxMemPool() : // accepting transactions becomes O(N^2) where N is the number // of transactions in the pool nCheckFrequency = 0; - - minerPolicyEstimator = new CBlockPolicyEstimator(); -} - -CTxMemPool::~CTxMemPool() -{ - delete minerPolicyEstimator; } bool CTxMemPool::isSpent(const COutPoint& outpoint) @@ -423,7 +414,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, nTransactionsUpdated++; totalTxSize += entry.GetTxSize(); - minerPolicyEstimator->processTransaction(entry, validFeeEstimate); + if (minerPolicyEstimator) {minerPolicyEstimator->processTransaction(entry, validFeeEstimate);} vTxHashes.emplace_back(hash, newit); newit->vTxHashesIdx = vTxHashes.size() - 1; @@ -701,7 +692,7 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) mapLinks.erase(it); mapTx.erase(it); nTransactionsUpdated++; - minerPolicyEstimator->removeTx(hash); + if (minerPolicyEstimator) {minerPolicyEstimator->removeTx(hash);} removeAddressIndex(hash); removeSpentIndex(hash); } @@ -976,7 +967,7 @@ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigne entries.push_back(&*i); } // Before the txs in the new block have been removed from the mempool, update policy estimates - minerPolicyEstimator->processBlock(nBlockHeight, entries); + if (minerPolicyEstimator) {minerPolicyEstimator->processBlock(nBlockHeight, entries);} for (const auto& tx : vtx) { txiter it = mapTx.find(tx->GetHash()); @@ -1325,51 +1316,6 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { return false; } -CFeeRate CTxMemPool::estimateFee(int nBlocks) const -{ - LOCK(cs); - return minerPolicyEstimator->estimateFee(nBlocks); -} -CFeeRate CTxMemPool::estimateSmartFee(int nBlocks, int *answerFoundAtBlocks) const -{ - LOCK(cs); - return minerPolicyEstimator->estimateSmartFee(nBlocks, answerFoundAtBlocks, *this); -} - -bool -CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const -{ - try { - LOCK(cs); - fileout << 120300; // version required to read: 0.12.00 or later - fileout << CLIENT_VERSION; // version that wrote the file - minerPolicyEstimator->Write(fileout); - } - catch (const std::exception&) { - LogPrintf("CTxMemPool::WriteFeeEstimates(): unable to write policy estimator data (non-fatal)\n"); - return false; - } - return true; -} - -bool -CTxMemPool::ReadFeeEstimates(CAutoFile& filein) -{ - try { - int nVersionRequired, nVersionThatWrote; - filein >> nVersionRequired >> nVersionThatWrote; - if (nVersionRequired > CLIENT_VERSION) - return error("CTxMemPool::ReadFeeEstimates(): up-version (%d) fee estimate file", nVersionRequired); - LOCK(cs); - minerPolicyEstimator->Read(filein, nVersionThatWrote); - } - catch (const std::exception&) { - LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy estimator data (non-fatal)\n"); - return false; - } - return true; -} - void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeDelta) { { diff --git a/src/txmempool.h b/src/txmempool.h index 3efd357570b0..91ece4b8c891 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -533,8 +533,7 @@ class CTxMemPool /** Create a new CTxMemPool. */ - CTxMemPool(); - ~CTxMemPool(); + CTxMemPool(CBlockPolicyEstimator* estimator = nullptr); /** * If sanity-checking is turned on, check makes sure the pool is @@ -679,19 +678,6 @@ class CTxMemPool bool existsProviderTxConflict(const CTransaction &tx) const; - /** Estimate fee rate needed to get into the next nBlocks - * If no answer can be given at nBlocks, return an estimate - * at the lowest number of blocks where one can be given - */ - CFeeRate estimateSmartFee(int nBlocks, int *answerFoundAtBlocks = NULL) const; - - /** Estimate fee rate needed to get into the next nBlocks */ - CFeeRate estimateFee(int nBlocks) const; - - /** Write/Read estimates to disk */ - bool WriteFeeEstimates(CAutoFile& fileout) const; - bool ReadFeeEstimates(CAutoFile& filein); - size_t DynamicMemoryUsage() const; // returns share of the used memory to maximum allowed memory double UsedMemoryShare() const; diff --git a/src/validation.cpp b/src/validation.cpp index bd5fea3ffcd1..8a6d4f0155b4 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -102,7 +102,8 @@ uint256 hashAssumeValid; CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE); CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; -CTxMemPool mempool; +CBlockPolicyEstimator feeEstimator; +CTxMemPool mempool(&feeEstimator); std::map mapRejectedBlocks GUARDED_BY(cs_main); static void CheckBlockIndex(const Consensus::Params& consensusParams); diff --git a/src/validation.h b/src/validation.h index 3f7aca5fc806..eae11a3a6568 100644 --- a/src/validation.h +++ b/src/validation.h @@ -42,6 +42,7 @@ class CCoinsViewDB; class CInv; class CConnman; class CScriptCheck; +class CBlockPolicyEstimator; class CTxMemPool; class CValidationInterface; class CValidationState; @@ -153,6 +154,7 @@ struct BlockHasher extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; +extern CBlockPolicyEstimator feeEstimator; extern CTxMemPool mempool; typedef boost::unordered_map BlockMap; typedef std::unordered_multimap PrevBlockMap; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index c221cbed5204..9f29f45238ea 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -12,6 +12,7 @@ #include "init.h" #include "instantsend.h" #include "net.h" +#include "policy/fees.h" #include "rpc/server.h" #include "timedata.h" #include "util.h" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0f9c462d6ee9..315685a52721 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -16,6 +16,7 @@ #include "keystore.h" #include "validation.h" #include "net.h" +#include "policy/fees.h" #include "policy/policy.h" #include "primitives/block.h" #include "primitives/transaction.h" @@ -3644,7 +3645,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (coinControl && coinControl->nConfirmTarget > 0) currentConfirmationTarget = coinControl->nConfirmTarget; - CAmount nFeeNeeded = std::max(nFeePay, GetMinimumFee(nBytes, currentConfirmationTarget, mempool)); + CAmount nFeeNeeded = std::max(nFeePay, GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator)); if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) { nFeeNeeded = coinControl->nMinimumTotalFee; } @@ -3817,19 +3818,19 @@ CAmount CWallet::GetRequiredFee(unsigned int nTxBytes) return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes)); } -CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) +CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator) { // payTxFee is the user-set global for desired feerate - return GetMinimumFee(nTxBytes, nConfirmTarget, pool, payTxFee.GetFee(nTxBytes)); + return GetMinimumFee(nTxBytes, nConfirmTarget, pool, estimator, payTxFee.GetFee(nTxBytes)); } -CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee) +CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, CAmount targetFee) { CAmount nFeeNeeded = targetFee; // User didn't set: use -txconfirmtarget to estimate... if (nFeeNeeded == 0) { int estimateFoundTarget = nConfirmTarget; - nFeeNeeded = pool.estimateSmartFee(nConfirmTarget, &estimateFoundTarget).GetFee(nTxBytes); + nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, &estimateFoundTarget, pool).GetFee(nTxBytes); // ... unless we don't have enough mempool data for estimatefee, then use fallbackFee if (nFeeNeeded == 0) nFeeNeeded = fallbackFee.GetFee(nTxBytes); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 4b57a1128f99..f7e080b5f85a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -81,6 +81,7 @@ class CReserveKey; class CScript; class CScheduler; class CTxMemPool; +class CBlockPolicyEstimator; class CWalletTx; /** (client) version numbers for particular wallet features */ @@ -1009,12 +1010,12 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Estimate the minimum fee considering user set parameters * and the required fee */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); + static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator); /** * Estimate the minimum fee considering required fee and targetFee or if 0 * then fee estimation for nConfirmTarget */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee); + static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, CAmount targetFee); /** * Return the minimum required fee taking into account the * floating relay fee and user set minimum transaction fee From 95f4cf44192d700cfc6e49b0fd5421e3479083a3 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 27 May 2019 17:00:26 -0500 Subject: [PATCH 120/987] add `#include "policy/fees.h"` to validation.cpp Signed-off-by: Pasta --- src/validation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/validation.cpp b/src/validation.cpp index 8a6d4f0155b4..8300858dac88 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -17,6 +17,7 @@ #include "consensus/validation.h" #include "hash.h" #include "init.h" +#include "policy/fees.h" #include "policy/policy.h" #include "pow.h" #include "primitives/block.h" From 60a8a935785b93b81c54ca026e28932dba5afda9 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 28 May 2019 01:36:26 +0300 Subject: [PATCH 121/987] Drop CDSNotificationInterface::SyncTransaction() --- src/dsnotificationinterface.cpp | 14 ++++---------- src/dsnotificationinterface.h | 2 -- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index f957a25b7556..2bd91ca87be4 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -72,18 +72,12 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con llmq::quorumDKGSessionManager->UpdatedBlockTip(pindexNew, fInitialDownload); } -void CDSNotificationInterface::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) -{ - // TODO when the old InstantSend system is removed, also remove this whole method and all the surrounding compatiblity code - instantsend.SyncTransaction(tx, pindex, posInBlock); -} - void CDSNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx) { llmq::quorumInstantSendManager->TransactionAddedToMempool(ptx); llmq::chainLocksHandler->TransactionAddedToMempool(ptx); CPrivateSend::TransactionAddedToMempool(ptx); - SyncTransaction(ptx); + instantsend.SyncTransaction(ptx); } void CDSNotificationInterface::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) @@ -101,10 +95,10 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptrvtx.size(); i++) { - SyncTransaction(pblock->vtx[i], pindex, i); + instantsend.SyncTransaction(pblock->vtx[i], pindex, i); } } @@ -115,7 +109,7 @@ void CDSNotificationInterface::BlockDisconnected(const std::shared_ptrvtx) { - SyncTransaction(ptx, pindexDisconnected->pprev, -1); + instantsend.SyncTransaction(ptx, pindexDisconnected->pprev, -1); } } diff --git a/src/dsnotificationinterface.h b/src/dsnotificationinterface.h index b8f480725d85..2ebcb92f8b78 100644 --- a/src/dsnotificationinterface.h +++ b/src/dsnotificationinterface.h @@ -29,8 +29,6 @@ class CDSNotificationInterface : public CValidationInterface private: CConnman& connman; - /* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected */ - void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); }; #endif // BITCOIN_DSNOTIFICATIONINTERFACE_H From e6a0b2162b7e2316512659e09edc6138c95ff3a1 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 28 May 2019 12:24:46 +0200 Subject: [PATCH 122/987] Add missing include for CKeyID --- src/txmempool.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/txmempool.h b/src/txmempool.h index 91ece4b8c891..08adff965879 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -23,6 +23,7 @@ #include "random.h" #include "netaddress.h" #include "bls/bls.h" +#include "pubkey.h" #include "boost/multi_index_container.hpp" #include "boost/multi_index/ordered_index.hpp" From 788973a8a659ed0a28925eaacf6a09a850d5662e Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 28 May 2019 13:56:48 +0300 Subject: [PATCH 123/987] Fix disconnect_ban.py We run tests in mocked time, need to bump it here for "remove from ban list after 1 sec" logic to triger. --- test/functional/disconnect_ban.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py index 3f451d49d23e..5c168b80d9e9 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/disconnect_ban.py @@ -11,6 +11,9 @@ connect_nodes_bi, start_node, stop_node, + set_mocktime, + get_mocktime, + set_node_times, ) class DisconnectBanTest(BitcoinTestFramework): @@ -64,6 +67,8 @@ def run_test(self): self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) # ban for 1000 seconds listBeforeShutdown = self.nodes[1].listbanned() assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) + set_mocktime(get_mocktime() + 2) + set_node_times(self.nodes, get_mocktime()) wait_until(lambda: len(self.nodes[1].listbanned()) == 3) stop_node(self.nodes[1], 1) From 81afb1058b1431c064117cf4824d9a66422e7347 Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 28 May 2019 08:36:28 -0500 Subject: [PATCH 124/987] remove `nodehandling.py` Signed-off-by: Pasta --- test/functional/nodehandling.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 test/functional/nodehandling.py diff --git a/test/functional/nodehandling.py b/test/functional/nodehandling.py deleted file mode 100755 index e69de29bb2d1..000000000000 From d36c408a68d97aef47c624d22cbdec70de9917a6 Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 28 May 2019 08:42:15 -0500 Subject: [PATCH 125/987] bump version in fees.cpp Signed-off-by: Pasta --- src/policy/fees.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 315509ce03d1..a14316aa7570 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -578,7 +578,7 @@ bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const { try { LOCK(cs_feeEstimator); - fileout << 139900; // version required to read: 0.13.99 or later + fileout << 140100; // version required to read: 0.14.1 or later fileout << CLIENT_VERSION; // version that wrote the file fileout << nBestSeenHeight; feeStats->Write(fileout); From 5780fa67074be71d400da10ff89d58761a0a1fe4 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 28 May 2019 20:32:51 +0300 Subject: [PATCH 126/987] Remove duplicate code from src/Makefile.am (#2944) Backported 10228 twice - in #1879 and #2911 --- src/Makefile.am | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 38f5077a4e78..eb5d42fdc0d6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -641,13 +641,6 @@ $(top_srcdir)/$(subdir)/config/dash-config.h.in: $(am__configure_deps) $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/dash-config.h.in -config/dash-config.h: config/stamp-h1 - @$(MAKE) -C $(top_builddir) $(subdir)/$(@) -config/stamp-h1: $(top_srcdir)/$(subdir)/config/dash-config.h.in $(top_builddir)/config.status - $(AM_V_at)$(MAKE) -C $(top_builddir) $(subdir)/$(@) -$(top_srcdir)/$(subdir)/config/dash-config.h.in: $(am__configure_deps) - $(AM_V_at)$(MAKE) -C $(top_srcdir) $(subdir)/config/dash-config.h.in - clean-local: -$(MAKE) -C secp256k1 clean -$(MAKE) -C univalue clean From 66b336c93768e8f9e52bd165179bcdcdc7d1a13e Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 29 May 2019 08:48:19 +0300 Subject: [PATCH 127/987] Use Travis stages instead of custom timeouts (#2948) --- .travis.yml | 105 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0c01d73825eb..47f090dfc879 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,15 +33,89 @@ env: - secure: "RLzlMhfLqwSBrZqJOVOd61suXBn+HtUR3vOZfuFYF/Qmjjj5TE41+rObZmzc54hP/ZL+OH6blnibpvfDXlX+eN38ivFQfuxkJIGL68SJsEwNBRwW39Yw6Hl5RdI41MLCH7ByN15wifLp1JKBilHJ7XGMOUjI7P0yl7JjX8GBXUCtJbVLRugo80/yn+XQ1NdnlpbpYHNjMEQFWSODPa3pSK5McWvyQjDZDgS+IkdrZmIYJPMa7bmKH5I/edUPSmXQT905FgEwq9u8XR0SyBopli21EK9l6GkXIIvmDTYz5vT26Apvi2B4Aoazlklg+KNRUJuLGerpt6kbnU0gMSUChVkFfFhOk6GRSN3a/AUfD2FOudvMhet2QvlPHx+GYdEUr5XVo5HW42pHsqfD6eDtHd8VLTsHP0q4C8V85fNMv21lkkehy2ry8fx/RRy6x4O2wg2mua+79UkGKXp75gMKzWEcth34PCFCOu37l2F8R/ANnrQ52K/8vIQ88TtU2OpYX89fHjLojBxu+WKEBGZH2LRPsZBOUHeeO5C/xKDrhZU24ORnMW8wg66Qg5GIX1KI4a8yp73Mpues5hzpJ6wkMuRrQt40ymKndLCjv8KSd+5BfP6Or/KIrzDNYdZaasjk7JNi6rcZmm9d3fTAo+Ja/mjpUCIOo3SX14luzVCJIig=" - DOCKER_BUILD=false - matrix: - - BUILD_TARGET=arm-linux - - BUILD_TARGET=win32 - - BUILD_TARGET=win64 - - BUILD_TARGET=linux32 - - BUILD_TARGET=linux64 - - BUILD_TARGET=linux64_nowallet - - BUILD_TARGET=linux64_release DOCKER_BUILD=true - - BUILD_TARGET=mac +stages: + - build depends + - build src + - run tests + - build docker + +builddepends: &builddepends + stage: build depends + script: + - $DOCKER_RUN_IN_BUILDER ./ci/build_depends.sh + +buildsrc: &buildsrc + stage: build src + script: + - $DOCKER_RUN_IN_BUILDER ./ci/build_depends.sh + - $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh + +runtests: &runtests + stage: run tests + script: + - $DOCKER_RUN_IN_BUILDER ./ci/build_depends.sh + - $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh + - $DOCKER_RUN_IN_BUILDER ./ci/test_unittests.sh + - $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh --jobs=3 + +builddocker: &builddocker + stage: build docker + script: + # no need to run tests again here + - if [ "$DOCKER_BUILD" = "true" ]; then $DOCKER_RUN_IN_BUILDER ./ci/build_depends.sh && $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh && BUILD_DIR=build-ci/dashcore-$BUILD_TARGET ./docker/build-docker.sh; fi + +jobs: + include: + # build depends + - <<: *builddepends + env: BUILD_TARGET=arm-linux + - <<: *builddepends + env: BUILD_TARGET=win32 + - <<: *builddepends + env: BUILD_TARGET=win64 + - <<: *builddepends + env: BUILD_TARGET=linux32 + - <<: *builddepends + env: BUILD_TARGET=linux64 + - <<: *builddepends + env: BUILD_TARGET=linux64_nowallet + - <<: *builddepends + env: BUILD_TARGET=linux64_release DOCKER_BUILD=true + - <<: *builddepends + env: BUILD_TARGET=mac + # build source + - <<: *buildsrc + env: BUILD_TARGET=arm-linux + - <<: *buildsrc + env: BUILD_TARGET=win32 + - <<: *buildsrc + env: BUILD_TARGET=win64 + - <<: *buildsrc + env: BUILD_TARGET=linux32 + - <<: *buildsrc + env: BUILD_TARGET=linux64 + - <<: *buildsrc + env: BUILD_TARGET=linux64_nowallet + - <<: *buildsrc + env: BUILD_TARGET=linux64_release DOCKER_BUILD=true + - <<: *buildsrc + env: BUILD_TARGET=mac + # run tests (no tests for arm-linux and mac) + - <<: *runtests + env: BUILD_TARGET=win32 + - <<: *runtests + env: BUILD_TARGET=win64 + - <<: *runtests + env: BUILD_TARGET=linux32 + - <<: *runtests + env: BUILD_TARGET=linux64 + - <<: *runtests + env: BUILD_TARGET=linux64_nowallet + - <<: *runtests + env: BUILD_TARGET=linux64_release DOCKER_BUILD=true + # build docker + - <<: *builddocker + env: BUILD_TARGET=linux64_release DOCKER_BUILD=true before_cache: # Save builder image @@ -53,6 +127,7 @@ install: - export JOB_NUMBER="$TRAVIS_JOB_NUMBER" - export HOST_SRC_DIR=$TRAVIS_BUILD_DIR - export HOST_CACHE_DIR=$HOME/cache + - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1` - source ./ci/matrix.sh - mkdir -p $HOST_CACHE_DIR/docker && mkdir -p $HOST_CACHE_DIR/ccache && mkdir -p $HOST_CACHE_DIR/depends && mkdir -p $HOST_CACHE_DIR/sdk-sources # Keep this as it makes caching related debugging easier @@ -67,18 +142,6 @@ before_script: - python3 -c 'import os,sys,fcntl; flags = fcntl.fcntl(sys.stdout, fcntl.F_GETFL); fcntl.fcntl(sys.stdout, fcntl.F_SETFL, flags&~os.O_NONBLOCK);' # Build docker image only for develop branch of the main repo - if [ "$TRAVIS_REPO_SLUG" != "dashpay/dash" -o "$TRAVIS_BRANCH" != "develop" -o "$TRAVIS_PULL_REQUEST" != "false" ]; then export DOCKER_BUILD="false"; echo DOCKER_BUILD=$DOCKER_BUILD; fi -script: - - export TRAVIS_COMMIT_LOG=`git log --format=fuller -1` - # Our scripts try to be Travis agnostic - - $DOCKER_RUN_IN_BUILDER ./ci/build_depends.sh; - # Gracefully stop build without running into timeouts (which won't update caches) when building depends or source took too long - # Next build should fix this situation as it will start with a populated cache - - if [ $SECONDS -gt 1200 ]; then export TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 - - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh - - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_unittests.sh - - if [ $SECONDS -gt 1800 -a "$RUN_INTEGRATIONTESTS" = "true" ]; then export TIMEOUT="true"; false; fi # The "false" here ensures that the build is marked as failed even though the whole script returns 0 - - test "$TIMEOUT" != "true" && $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh --jobs=3 - - test "$TIMEOUT" != "true" && if [ "$DOCKER_BUILD" = "true" ]; then BUILD_DIR=build-ci/dashcore-$BUILD_TARGET ./docker/build-docker.sh; fi after_script: - echo $TRAVIS_COMMIT_RANGE - echo $TRAVIS_COMMIT_LOG From 186f7d2861637626eead85204cfe50ab31d0eafa Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 28 May 2019 15:15:37 +0200 Subject: [PATCH 128/987] Implement support for explicit enum serialization This allows to serialize enum values, but only if a specialized class of is_serializable_enum is found which is derived from std::true_type. --- src/serialize.h | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index 99801f7e50dd..268c70396f99 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -720,20 +720,52 @@ template void Unserialize(Stream& os, std::unique_p /** - * If none of the specialized versions above matched, default to calling member function. + * If none of the specialized versions above matched and T is a class, default to calling member function. */ -template +template::value>::type* = nullptr> inline void Serialize(Stream& os, const T& a) { a.Serialize(os); } -template +template::value>::type* = nullptr> inline void Unserialize(Stream& is, T& a) { a.Unserialize(is); } +/** + * If none of the specialized versions above matched and T is an enum, default to calling + * Serialize/Unserialze with the underlying type. This is only allowed when a specialized struct of is_serializable_enum + * is found which derives from std::true_type. This is to ensure that enums are not serialized with the wrong type by + * accident. + */ + +template struct is_serializable_enum; +template struct is_serializable_enum : std::false_type {}; + +template::value>::type* = nullptr> +inline void Serialize(Stream& s, T a ) +{ + // If you ever get into this situation, it usaully means you forgot to declare is_serializable_enum for the desired enum type + static_assert(is_serializable_enum::value); + + typedef typename std::underlying_type::type T2; + T2 b = (T2)a; + Serialize(s, b); +} + +template::value>::type* = nullptr> +inline void Unserialize(Stream& s, T& a ) +{ + // If you ever get into this situation, it usaully means you forgot to declare is_serializable_enum for the desired enum type + static_assert(is_serializable_enum::value); + + typedef typename std::underlying_type::type T2; + T2 b; + Unserialize(s, b); + a = (T)b; +} From 40fd1b16858fbc2ec6e9606c1206422b3aa53adf Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 28 May 2019 15:34:41 +0200 Subject: [PATCH 129/987] Make Consensus::LLMQType serializable and use it in serialized classes Instead of using uint8_t and explicitely casting between the enum and uint8_t. --- src/consensus/params.h | 5 +++++ src/llmq/quorums.cpp | 2 +- src/llmq/quorums_blockprocessor.cpp | 14 ++++++------ src/llmq/quorums_commitment.cpp | 2 +- src/llmq/quorums_commitment.h | 2 +- src/llmq/quorums_debug.cpp | 2 +- src/llmq/quorums_debug.h | 4 ++-- src/llmq/quorums_dkgsession.cpp | 8 +++---- src/llmq/quorums_dkgsession.h | 8 +++---- src/llmq/quorums_dkgsessionmgr.cpp | 8 +++---- src/llmq/quorums_signing.cpp | 34 ++++++++++++++--------------- src/llmq/quorums_signing.h | 2 +- src/llmq/quorums_signing_shares.cpp | 2 +- src/llmq/quorums_signing_shares.h | 4 ++-- src/llmq/quorums_utils.cpp | 8 +++---- src/llmq/quorums_utils.h | 2 +- 16 files changed, 56 insertions(+), 51 deletions(-) diff --git a/src/consensus/params.h b/src/consensus/params.h index 9fae740720da..aed42328e62b 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -183,4 +183,9 @@ struct Params { }; } // namespace Consensus +// This must be outside of all namespaces. We must also duplicate the forward declaration of is_serializable_enum to +// avoid inclusion of serialize.h here. +template struct is_serializable_enum; +template<> struct is_serializable_enum : std::true_type {}; + #endif // BITCOIN_CONSENSUS_PARAMS_H diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index fcea77968b2a..d3063ad9f54d 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -32,7 +32,7 @@ CQuorumManager* quorumManager; static uint256 MakeQuorumKey(const CQuorum& q) { CHashWriter hw(SER_NETWORK, 0); - hw << (uint8_t)q.params.type; + hw << q.params.type; hw << q.qc.quorumHash; for (const auto& dmn : q.members) { hw << dmn->proTxHash; diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index df72050d60a4..302600fe6a04 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -168,10 +168,10 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, const CBlockIndex* // We store a mapping from minedHeight->quorumHeight in the DB // minedHeight is inversed so that entries are traversable in reversed order -static std::tuple BuildInversedHeightKey(Consensus::LLMQType llmqType, int nMinedHeight) +static std::tuple BuildInversedHeightKey(Consensus::LLMQType llmqType, int nMinedHeight) { // nMinedHeight must be converted to big endian to make it comparable when serialized - return std::make_tuple(DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT, (uint8_t)llmqType, htobe32(std::numeric_limits::max() - nMinedHeight)); + return std::make_tuple(DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT, llmqType, htobe32(std::numeric_limits::max() - nMinedHeight)); } bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockHash, const CFinalCommitment& qc, CValidationState& state) @@ -211,7 +211,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH // Store commitment in DB auto quorumIndex = mapBlockIndex.at(qc.quorumHash); - evoDb.Write(std::make_pair(DB_MINED_COMMITMENT, std::make_pair((uint8_t)params.type, quorumHash)), std::make_pair(qc, blockHash)); + evoDb.Write(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(params.type, quorumHash)), std::make_pair(qc, blockHash)); evoDb.Write(BuildInversedHeightKey(params.type, nHeight), quorumIndex->nHeight); { @@ -285,7 +285,7 @@ void CQuorumBlockProcessor::UpgradeDB() continue; } auto quorumIndex = mapBlockIndex.at(qc.quorumHash); - evoDb.GetRawDB().Write(std::make_pair(DB_MINED_COMMITMENT, std::make_pair((uint8_t)qc.llmqType, qc.quorumHash)), std::make_pair(qc, pindex->GetBlockHash())); + evoDb.GetRawDB().Write(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(qc.llmqType, qc.quorumHash)), std::make_pair(qc, pindex->GetBlockHash())); evoDb.GetRawDB().Write(BuildInversedHeightKey((Consensus::LLMQType)qc.llmqType, pindex->nHeight), quorumIndex->nHeight); } @@ -381,7 +381,7 @@ bool CQuorumBlockProcessor::HasMinedCommitment(Consensus::LLMQType llmqType, con } } - auto key = std::make_pair(DB_MINED_COMMITMENT, std::make_pair((uint8_t)llmqType, quorumHash)); + auto key = std::make_pair(DB_MINED_COMMITMENT, std::make_pair(llmqType, quorumHash)); bool ret = evoDb.Exists(key); LOCK(minableCommitmentsCs); @@ -391,7 +391,7 @@ bool CQuorumBlockProcessor::HasMinedCommitment(Consensus::LLMQType llmqType, con bool CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, const uint256& quorumHash, CFinalCommitment& retQc, uint256& retMinedBlockHash) { - auto key = std::make_pair(DB_MINED_COMMITMENT, std::make_pair((uint8_t)llmqType, quorumHash)); + auto key = std::make_pair(DB_MINED_COMMITMENT, std::make_pair(llmqType, quorumHash)); std::pair p; if (!evoDb.Read(key, p)) { return false; @@ -419,7 +419,7 @@ std::vector CQuorumBlockProcessor::GetMinedCommitmentsUntilB if (!dbIt->GetKey(curKey) || curKey >= lastKey) { break; } - if (std::get<0>(curKey) != DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT || std::get<1>(curKey) != (uint8_t)llmqType) { + if (std::get<0>(curKey) != DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT || std::get<1>(curKey) != llmqType) { break; } diff --git a/src/llmq/quorums_commitment.cpp b/src/llmq/quorums_commitment.cpp index 83d9c7727e78..ea26b24ea733 100644 --- a/src/llmq/quorums_commitment.cpp +++ b/src/llmq/quorums_commitment.cpp @@ -81,7 +81,7 @@ bool CFinalCommitment::Verify(const std::vector& members, // sigs are only checked when the block is processed if (checkSigs) { - uint256 commitmentHash = CLLMQUtils::BuildCommitmentHash((uint8_t)params.type, quorumHash, validMembers, quorumPublicKey, quorumVvecHash); + uint256 commitmentHash = CLLMQUtils::BuildCommitmentHash(params.type, quorumHash, validMembers, quorumPublicKey, quorumVvecHash); std::vector memberPubKeys; for (size_t i = 0; i < members.size(); i++) { diff --git a/src/llmq/quorums_commitment.h b/src/llmq/quorums_commitment.h index de5ccbf2deb0..f2c27372b7a5 100644 --- a/src/llmq/quorums_commitment.h +++ b/src/llmq/quorums_commitment.h @@ -24,7 +24,7 @@ class CFinalCommitment public: uint16_t nVersion{CURRENT_VERSION}; - uint8_t llmqType{Consensus::LLMQ_NONE}; + Consensus::LLMQType llmqType{Consensus::LLMQ_NONE}; uint256 quorumHash; std::vector signers; std::vector validMembers; diff --git a/src/llmq/quorums_debug.cpp b/src/llmq/quorums_debug.cpp index dba8963e946c..2dec5c04e98a 100644 --- a/src/llmq/quorums_debug.cpp +++ b/src/llmq/quorums_debug.cpp @@ -151,7 +151,7 @@ void CDKGDebugManager::InitLocalSessionStatus(Consensus::LLMQType llmqType, cons auto it = localStatus.sessions.find(llmqType); if (it == localStatus.sessions.end()) { - it = localStatus.sessions.emplace((uint8_t)llmqType, CDKGDebugSessionStatus()).first; + it = localStatus.sessions.emplace(llmqType, CDKGDebugSessionStatus()).first; } auto& params = Params().GetConsensus().llmqs.at(llmqType); diff --git a/src/llmq/quorums_debug.h b/src/llmq/quorums_debug.h index b52dec66695b..e6eaa1ba3689 100644 --- a/src/llmq/quorums_debug.h +++ b/src/llmq/quorums_debug.h @@ -47,7 +47,7 @@ class CDKGDebugMemberStatus class CDKGDebugSessionStatus { public: - uint8_t llmqType{Consensus::LLMQ_NONE}; + Consensus::LLMQType llmqType{Consensus::LLMQ_NONE}; uint256 quorumHash; uint32_t quorumHeight{0}; uint8_t phase{0}; @@ -79,7 +79,7 @@ class CDKGDebugStatus public: int64_t nTime{0}; - std::map sessions; + std::map sessions; public: UniValue ToJson(int detailLevel) const; diff --git a/src/llmq/quorums_dkgsession.cpp b/src/llmq/quorums_dkgsession.cpp index c68db08bb154..32e3accccabf 100644 --- a/src/llmq/quorums_dkgsession.cpp +++ b/src/llmq/quorums_dkgsession.cpp @@ -169,7 +169,7 @@ void CDKGSession::SendContributions(CDKGPendingMessages& pendingMessages) } CDKGContribution qc; - qc.llmqType = (uint8_t)params.type; + qc.llmqType = params.type; qc.quorumHash = quorumHash; qc.proTxHash = myProTxHash; qc.vvec = vvecContribution; @@ -448,7 +448,7 @@ void CDKGSession::SendComplaint(CDKGPendingMessages& pendingMessages) assert(AreWeMember()); CDKGComplaint qc(params); - qc.llmqType = (uint8_t)params.type; + qc.llmqType = params.type; qc.quorumHash = quorumHash; qc.proTxHash = myProTxHash; @@ -642,7 +642,7 @@ void CDKGSession::SendJustification(CDKGPendingMessages& pendingMessages, const logger.Batch("sending justification for %d members", forMembers.size()); CDKGJustification qj; - qj.llmqType = (uint8_t)params.type; + qj.llmqType = params.type; qj.quorumHash = quorumHash; qj.proTxHash = myProTxHash; qj.contributions.reserve(forMembers.size()); @@ -898,7 +898,7 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages) logger.Batch("sending commitment"); CDKGPrematureCommitment qc(params); - qc.llmqType = (uint8_t)params.type; + qc.llmqType = params.type; qc.quorumHash = quorumHash; qc.proTxHash = myProTxHash; diff --git a/src/llmq/quorums_dkgsession.h b/src/llmq/quorums_dkgsession.h index e6a23a5f6bb5..489d3121c017 100644 --- a/src/llmq/quorums_dkgsession.h +++ b/src/llmq/quorums_dkgsession.h @@ -36,7 +36,7 @@ class CDKGLogger : public CBatchedLogger class CDKGContribution { public: - uint8_t llmqType; + Consensus::LLMQType llmqType; uint256 quorumHash; uint256 proTxHash; BLSVerificationVectorPtr vvec; @@ -88,7 +88,7 @@ class CDKGContribution class CDKGComplaint { public: - uint8_t llmqType; + Consensus::LLMQType llmqType; uint256 quorumHash; uint256 proTxHash; std::vector badMembers; @@ -123,7 +123,7 @@ class CDKGComplaint class CDKGJustification { public: - uint8_t llmqType; + Consensus::LLMQType llmqType; uint256 quorumHash; uint256 proTxHash; std::vector> contributions; @@ -157,7 +157,7 @@ class CDKGJustification class CDKGPrematureCommitment { public: - uint8_t llmqType; + Consensus::LLMQType llmqType; uint256 quorumHash; uint256 proTxHash; std::vector validMembers; diff --git a/src/llmq/quorums_dkgsessionmgr.cpp b/src/llmq/quorums_dkgsessionmgr.cpp index c68d95d00ad8..1f081a4a1ea6 100644 --- a/src/llmq/quorums_dkgsessionmgr.cpp +++ b/src/llmq/quorums_dkgsessionmgr.cpp @@ -200,12 +200,12 @@ bool CDKGSessionManager::GetPrematureCommitment(const uint256& hash, CDKGPrematu void CDKGSessionManager::WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& proTxHash, const BLSVerificationVectorPtr& vvec) { - llmqDb.Write(std::make_tuple(DB_VVEC, (uint8_t)llmqType, quorumHash, proTxHash), *vvec); + llmqDb.Write(std::make_tuple(DB_VVEC, llmqType, quorumHash, proTxHash), *vvec); } void CDKGSessionManager::WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& proTxHash, const CBLSSecretKey& skContribution) { - llmqDb.Write(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, quorumHash, proTxHash), skContribution); + llmqDb.Write(std::make_tuple(DB_SKCONTRIB, llmqType, quorumHash, proTxHash), skContribution); } bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::vector& validMembers, std::vector& memberIndexesRet, std::vector& vvecsRet, BLSSecretKeyVector& skContributionsRet) @@ -248,10 +248,10 @@ bool CDKGSessionManager::GetVerifiedContribution(Consensus::LLMQType llmqType, c BLSVerificationVector vvec; BLSVerificationVectorPtr vvecPtr; CBLSSecretKey skContribution; - if (llmqDb.Read(std::make_tuple(DB_VVEC, (uint8_t)llmqType, quorumHash, proTxHash), vvec)) { + if (llmqDb.Read(std::make_tuple(DB_VVEC, llmqType, quorumHash, proTxHash), vvec)) { vvecPtr = std::make_shared(std::move(vvec)); } - llmqDb.Read(std::make_tuple(DB_SKCONTRIB, (uint8_t)llmqType, quorumHash, proTxHash), skContribution); + llmqDb.Read(std::make_tuple(DB_SKCONTRIB, llmqType, quorumHash, proTxHash), skContribution); it = contributionsCache.emplace(cacheKey, ContributionsCacheEntry{GetTimeMillis(), vvecPtr, skContribution}).first; diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index cd5f74f45aa5..8ae80c60634a 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -59,7 +59,7 @@ void CRecoveredSigsDb::ConvertInvalidTimeKeys() std::unique_ptr pcursor(db.NewIterator()); - auto start = std::make_tuple(std::string("rs_t"), (uint32_t)0, (uint8_t)0, uint256()); + auto start = std::make_tuple(std::string("rs_t"), (uint32_t)0, (Consensus::LLMQType)0, uint256()); pcursor->Seek(start); CDBBatch batch(db); @@ -96,7 +96,7 @@ void CRecoveredSigsDb::AddVoteTimeKeys() std::unique_ptr pcursor(db.NewIterator()); - auto start = std::make_tuple(std::string("rs_v"), (uint8_t)0, uint256()); + auto start = std::make_tuple(std::string("rs_v"), (Consensus::LLMQType)0, uint256()); pcursor->Seek(start); CDBBatch batch(db); @@ -108,7 +108,7 @@ void CRecoveredSigsDb::AddVoteTimeKeys() break; } - uint8_t llmqType = std::get<1>(k); + Consensus::LLMQType llmqType = std::get<1>(k); const uint256& id = std::get<2>(k); auto k2 = std::make_tuple(std::string("rs_vt"), (uint32_t)htobe32(curTime), llmqType, id); @@ -127,7 +127,7 @@ void CRecoveredSigsDb::AddVoteTimeKeys() bool CRecoveredSigsDb::HasRecoveredSig(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash) { - auto k = std::make_tuple(std::string("rs_r"), (uint8_t)llmqType, id, msgHash); + auto k = std::make_tuple(std::string("rs_r"), llmqType, id, msgHash); return db.Exists(k); } @@ -143,7 +143,7 @@ bool CRecoveredSigsDb::HasRecoveredSigForId(Consensus::LLMQType llmqType, const } - auto k = std::make_tuple(std::string("rs_r"), (uint8_t)llmqType, id); + auto k = std::make_tuple(std::string("rs_r"), llmqType, id); ret = db.Exists(k); LOCK(cs); @@ -189,7 +189,7 @@ bool CRecoveredSigsDb::HasRecoveredSigForHash(const uint256& hash) bool CRecoveredSigsDb::ReadRecoveredSig(Consensus::LLMQType llmqType, const uint256& id, CRecoveredSig& ret) { - auto k = std::make_tuple(std::string("rs_r"), (uint8_t)llmqType, id); + auto k = std::make_tuple(std::string("rs_r"), llmqType, id); CDataStream ds(SER_DISK, CLIENT_VERSION); if (!db.ReadDataStream(k, ds)) { @@ -207,12 +207,12 @@ bool CRecoveredSigsDb::ReadRecoveredSig(Consensus::LLMQType llmqType, const uint bool CRecoveredSigsDb::GetRecoveredSigByHash(const uint256& hash, CRecoveredSig& ret) { auto k1 = std::make_tuple(std::string("rs_h"), hash); - std::pair k2; + std::pair k2; if (!db.Read(k1, k2)) { return false; } - return ReadRecoveredSig((Consensus::LLMQType)k2.first, k2.second, ret); + return ReadRecoveredSig(k2.first, k2.second, ret); } bool CRecoveredSigsDb::GetRecoveredSigById(Consensus::LLMQType llmqType, const uint256& id, CRecoveredSig& ret) @@ -260,7 +260,7 @@ void CRecoveredSigsDb::CleanupOldRecoveredSigs(int64_t maxAge) { std::unique_ptr pcursor(db.NewIterator()); - auto start = std::make_tuple(std::string("rs_t"), (uint32_t)0, (uint8_t)0, uint256()); + auto start = std::make_tuple(std::string("rs_t"), (uint32_t)0, (Consensus::LLMQType)0, uint256()); uint32_t endTime = (uint32_t)(GetAdjustedTime() - maxAge); pcursor->Seek(start); @@ -277,7 +277,7 @@ void CRecoveredSigsDb::CleanupOldRecoveredSigs(int64_t maxAge) break; } - toDelete.emplace_back((Consensus::LLMQType)std::get<2>(k), std::get<3>(k)); + toDelete.emplace_back(std::get<2>(k), std::get<3>(k)); toDelete2.emplace_back(k); pcursor->Next(); @@ -330,20 +330,20 @@ void CRecoveredSigsDb::CleanupOldRecoveredSigs(int64_t maxAge) bool CRecoveredSigsDb::HasVotedOnId(Consensus::LLMQType llmqType, const uint256& id) { - auto k = std::make_tuple(std::string("rs_v"), (uint8_t)llmqType, id); + auto k = std::make_tuple(std::string("rs_v"), llmqType, id); return db.Exists(k); } bool CRecoveredSigsDb::GetVoteForId(Consensus::LLMQType llmqType, const uint256& id, uint256& msgHashRet) { - auto k = std::make_tuple(std::string("rs_v"), (uint8_t)llmqType, id); + auto k = std::make_tuple(std::string("rs_v"), llmqType, id); return db.Read(k, msgHashRet); } void CRecoveredSigsDb::WriteVoteForId(Consensus::LLMQType llmqType, const uint256& id, const uint256& msgHash) { - auto k1 = std::make_tuple(std::string("rs_v"), (uint8_t)llmqType, id); - auto k2 = std::make_tuple(std::string("rs_vt"), (uint32_t)htobe32(GetAdjustedTime()), (uint8_t)llmqType, id); + auto k1 = std::make_tuple(std::string("rs_v"), llmqType, id); + auto k2 = std::make_tuple(std::string("rs_vt"), (uint32_t)htobe32(GetAdjustedTime()), llmqType, id); CDBBatch batch(db); batch.Write(k1, msgHash); @@ -356,7 +356,7 @@ void CRecoveredSigsDb::CleanupOldVotes(int64_t maxAge) { std::unique_ptr pcursor(db.NewIterator()); - auto start = std::make_tuple(std::string("rs_vt"), (uint32_t)0, (uint8_t)0, uint256()); + auto start = std::make_tuple(std::string("rs_vt"), (uint32_t)0, (Consensus::LLMQType)0, uint256()); uint32_t endTime = (uint32_t)(GetAdjustedTime() - maxAge); pcursor->Seek(start); @@ -372,7 +372,7 @@ void CRecoveredSigsDb::CleanupOldVotes(int64_t maxAge) break; } - uint8_t llmqType = std::get<2>(k); + Consensus::LLMQType llmqType = std::get<2>(k); const uint256& id = std::get<3>(k); batch.Erase(k); @@ -839,7 +839,7 @@ CQuorumCPtr CSigningManager::SelectQuorumForSigning(Consensus::LLMQType llmqType scores.reserve(quorums.size()); for (size_t i = 0; i < quorums.size(); i++) { CHashWriter h(SER_NETWORK, 0); - h << (uint8_t)llmqType; + h << llmqType; h << quorums[i]->qc.quorumHash; h << selectionHash; scores.emplace_back(h.GetHash(), i); diff --git a/src/llmq/quorums_signing.h b/src/llmq/quorums_signing.h index 1916a66e6a82..509a870a6859 100644 --- a/src/llmq/quorums_signing.h +++ b/src/llmq/quorums_signing.h @@ -21,7 +21,7 @@ namespace llmq class CRecoveredSig { public: - uint8_t llmqType; + Consensus::LLMQType llmqType; uint256 quorumHash; uint256 id; uint256 msgHash; diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index 42d4f3f55a50..1e90e27ca714 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -998,7 +998,7 @@ bool CSigSharesManager::SendMessages() CSigSesAnn sigSesAnn; sigSesAnn.sessionId = session->sendSessionId; - sigSesAnn.llmqType = (uint8_t)session->llmqType; + sigSesAnn.llmqType = session->llmqType; sigSesAnn.quorumHash = session->quorumHash; sigSesAnn.id = session->id; sigSesAnn.msgHash = session->msgHash; diff --git a/src/llmq/quorums_signing_shares.h b/src/llmq/quorums_signing_shares.h index f355ca4a81c2..4dc82c7a3374 100644 --- a/src/llmq/quorums_signing_shares.h +++ b/src/llmq/quorums_signing_shares.h @@ -34,7 +34,7 @@ typedef std::pair SigShareKey; class CSigShare { public: - uint8_t llmqType; + Consensus::LLMQType llmqType; uint256 quorumHash; uint16_t quorumMember; uint256 id; @@ -63,7 +63,7 @@ class CSigSesAnn { public: uint32_t sessionId{(uint32_t)-1}; - uint8_t llmqType; + Consensus::LLMQType llmqType; uint256 quorumHash; uint256 id; uint256 msgHash; diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index 338b01bf54c7..2b48d0796389 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -16,11 +16,11 @@ std::vector CLLMQUtils::GetAllQuorumMembers(Consensus::LLM { auto& params = Params().GetConsensus().llmqs.at(llmqType); auto allMns = deterministicMNManager->GetListForBlock(blockHash); - auto modifier = ::SerializeHash(std::make_pair((uint8_t)llmqType, blockHash)); + auto modifier = ::SerializeHash(std::make_pair(llmqType, blockHash)); return allMns.CalculateQuorum(params.size, modifier); } -uint256 CLLMQUtils::BuildCommitmentHash(uint8_t llmqType, const uint256& blockHash, const std::vector& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash) +uint256 CLLMQUtils::BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256& blockHash, const std::vector& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash) { CHashWriter hw(SER_NETWORK, 0); hw << llmqType; @@ -34,7 +34,7 @@ uint256 CLLMQUtils::BuildCommitmentHash(uint8_t llmqType, const uint256& blockHa uint256 CLLMQUtils::BuildSignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash) { CHashWriter h(SER_GETHASH, 0); - h << (uint8_t)llmqType; + h << llmqType; h << quorumHash; h << id; h << msgHash; @@ -89,7 +89,7 @@ std::set CLLMQUtils::CalcDeterministicWatchConnections(Consensus::LLMQTy std::set result; uint256 rnd = qwatchConnectionSeed; for (size_t i = 0; i < connectionCount; i++) { - rnd = ::SerializeHash(std::make_pair(rnd, std::make_pair((uint8_t)llmqType, blockHash))); + rnd = ::SerializeHash(std::make_pair(rnd, std::make_pair(llmqType, blockHash))); result.emplace(rnd.GetUint64(0) % memberCount); } return result; diff --git a/src/llmq/quorums_utils.h b/src/llmq/quorums_utils.h index a8c5ba7924bb..0a6fd40ff40f 100644 --- a/src/llmq/quorums_utils.h +++ b/src/llmq/quorums_utils.h @@ -21,7 +21,7 @@ class CLLMQUtils // includes members which failed DKG static std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, const uint256& blockHash); - static uint256 BuildCommitmentHash(uint8_t llmqType, const uint256& blockHash, const std::vector& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash); + static uint256 BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256& blockHash, const std::vector& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash); static uint256 BuildSignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash); // works for sig shares and recovered sigs From b74cd3e1019877a8436bbf67c20d62727ff341db Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Wed, 29 May 2019 10:56:51 +0200 Subject: [PATCH 130/987] Only require valid collaterals for votes and triggers (#2947) * Only require valid collaterals for votes and triggers * Bump proto version * Only announce votes from banned MNs to >= 70215 proto version nodes --- src/governance/governance-object.cpp | 8 -------- src/governance/governance-object.h | 1 + src/governance/governance-vote.cpp | 17 +++++++++++++++-- src/version.h | 2 +- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/governance/governance-object.cpp b/src/governance/governance-object.cpp index 69b95352e991..bd137c6caae5 100644 --- a/src/governance/governance-object.cpp +++ b/src/governance/governance-object.cpp @@ -498,14 +498,6 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingMast strError = "Failed to find Masternode by UTXO, missing masternode=" + strOutpoint; return false; } - if (!mnList.IsMNValid(dmn)) { - if (mnList.IsMNPoSeBanned(dmn)) { - strError = "Masternode is POSE_BANNED, masternode=" + strOutpoint; - } else { - strError = "Masternode is invalid for unknown reason, masternode=" + strOutpoint; - } - return false; - } // Check that we have a valid MN signature if (!CheckSignature(dmn->pdmnState->pubKeyOperator)) { diff --git a/src/governance/governance-object.h b/src/governance/governance-object.h index 30d7a66aec85..21659c275daf 100644 --- a/src/governance/governance-object.h +++ b/src/governance/governance-object.h @@ -25,6 +25,7 @@ class CGovernanceVote; static const int MIN_GOVERNANCE_PEER_PROTO_VERSION = 70213; static const int GOVERNANCE_FILTER_PROTO_VERSION = 70206; +static const int GOVERNANCE_POSE_BANNED_VOTES_VERSION = 70215; static const double GOVERNANCE_FILTER_FP_RATE = 0.001; diff --git a/src/governance/governance-vote.cpp b/src/governance/governance-vote.cpp index 53816bc8a30e..5836e78a9fb6 100644 --- a/src/governance/governance-vote.cpp +++ b/src/governance/governance-vote.cpp @@ -120,8 +120,21 @@ void CGovernanceVote::Relay(CConnman& connman) const return; } + auto mnList = deterministicMNManager->GetListAtChainTip(); + auto dmn = mnList.GetMNByCollateral(masternodeOutpoint); + if (!dmn) { + return; + } + + // When this vote is from non-valid (PoSe banned) MN, we should only announce it to v0.14.0.1 nodes as older nodes + // will ban us otherwise. + int minVersion = MIN_GOVERNANCE_PEER_PROTO_VERSION; + if (!mnList.IsMNValid(dmn)) { + minVersion = GOVERNANCE_POSE_BANNED_VOTES_VERSION; + } + CInv inv(MSG_GOVERNANCE_OBJECT_VOTE, GetHash()); - connman.RelayInv(inv, MIN_GOVERNANCE_PEER_PROTO_VERSION); + connman.RelayInv(inv, minVersion); } void CGovernanceVote::UpdateHash() const @@ -258,7 +271,7 @@ bool CGovernanceVote::IsValid(bool useVotingKey) const return false; } - auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(masternodeOutpoint); + auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(masternodeOutpoint); if (!dmn) { LogPrint(BCLog::GOBJECT, "CGovernanceVote::IsValid -- Unknown Masternode - %s\n", masternodeOutpoint.ToStringShort()); return false; diff --git a/src/version.h b/src/version.h index 680c2a070d53..148cfd2e3645 100644 --- a/src/version.h +++ b/src/version.h @@ -11,7 +11,7 @@ */ -static const int PROTOCOL_VERSION = 70214; +static const int PROTOCOL_VERSION = 70215; //! initial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; From a149ca7471a171959d1e0c3bcfc88d8884fa448f Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Wed, 29 May 2019 13:18:15 -0500 Subject: [PATCH 131/987] Remove references to instantx and darksend in sendcoinsdialog.cpp (#2936) * bUseInstantX -> bUseInstantSend & bUseDarkSend -> bUsePrivateSend and be backwords compatible Signed-off-by: Pasta * remove old settings Signed-off-by: Pasta --- src/qt/sendcoinsdialog.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 82661e059df8..d9757c704dc9 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -71,13 +71,24 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p // Dash specific QSettings settings; - if (!settings.contains("bUseDarkSend")) - settings.setValue("bUseDarkSend", false); - if (!settings.contains("bUseInstantX")) - settings.setValue("bUseInstantX", false); + //TODO remove Darksend sometime after 0.14.1 + if (settings.contains("bUseDarkSend")) { + settings.setValue("bUsePrivateSend", settings.value("bUseDarkSend").toBool()); + settings.remove("bUseDarkSend"); + } + if (!settings.contains("bUsePrivateSend")) + settings.setValue("bUsePrivateSend", false); + + //TODO remove InstantX sometime after 0.14.1 + if (settings.contains("bUseInstantX")) { + settings.setValue("bUseInstantSend", settings.value("bUseInstantX").toBool()); + settings.remove("bUseInstantX"); + } + if (!settings.contains("bUseInstantSend")) + settings.setValue("bUseInstantSend", false); - bool fUsePrivateSend = settings.value("bUseDarkSend").toBool(); - bool fUseInstantSend = settings.value("bUseInstantX").toBool(); + bool fUsePrivateSend = settings.value("bUsePrivateSend").toBool(); + bool fUseInstantSend = settings.value("bUseInstantSend").toBool(); if(fLiteMode) { ui->checkUsePrivateSend->setChecked(false); ui->checkUsePrivateSend->setVisible(false); @@ -586,7 +597,7 @@ void SendCoinsDialog::setBalance(const CAmount& balance, const CAmount& unconfir { uint64_t bal = 0; QSettings settings; - settings.setValue("bUseDarkSend", ui->checkUsePrivateSend->isChecked()); + settings.setValue("bUsePrivateSend", ui->checkUsePrivateSend->isChecked()); if(ui->checkUsePrivateSend->isChecked()) { bal = anonymizedBalance; } else { @@ -611,7 +622,7 @@ void SendCoinsDialog::updateDisplayUnit() void SendCoinsDialog::updateInstantSend() { QSettings settings; - settings.setValue("bUseInstantX", ui->checkUseInstantSend->isChecked()); + settings.setValue("bUseInstantSend", ui->checkUseInstantSend->isChecked()); CoinControlDialog::coinControl->fUseInstantSend = model->IsOldInstantSendEnabled() && ui->checkUseInstantSend->isChecked(); coinControlUpdateLabels(); } From fc73b4d6e6cc1ee4987d026aa3b8027ef0dbe77f Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Wed, 29 May 2019 20:18:31 +0200 Subject: [PATCH 132/987] Refactor sporks to get rid of repeated if/else blocks (#2946) * Use enum to define spork IDs * Introduce CSporkDef and remove if/else blocks in GetSporkIDByName/GetSporkNameByID * Deduplicate code in IsSporkActive * Fix spork RPC to use new spork defs This also removes the need for SPORK_START/SPORK_END * Move sporkManager global variable below sporkDefs This ensures correct order of initialization. --- src/rpc/misc.cpp | 14 +++--- src/spork.cpp | 111 ++++++++++++++++++++--------------------------- src/spork.h | 68 +++++++++++++++++------------ 3 files changed, 92 insertions(+), 101 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index b226f39bd156..779527971293 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -253,16 +253,14 @@ UniValue spork(const JSONRPCRequest& request) std:: string strCommand = request.params[0].get_str(); if (strCommand == "show") { UniValue ret(UniValue::VOBJ); - for(int nSporkID = SPORK_START; nSporkID <= SPORK_END; nSporkID++){ - if(sporkManager.GetSporkNameByID(nSporkID) != "Unknown") - ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.GetSporkValue(nSporkID))); + for (const auto& sporkDef : sporkDefs) { + ret.push_back(Pair(sporkDef.name, sporkManager.GetSporkValue(sporkDef.sporkId))); } return ret; } else if(strCommand == "active"){ UniValue ret(UniValue::VOBJ); - for(int nSporkID = SPORK_START; nSporkID <= SPORK_END; nSporkID++){ - if(sporkManager.GetSporkNameByID(nSporkID) != "Unknown") - ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.IsSporkActive(nSporkID))); + for (const auto& sporkDef : sporkDefs) { + ret.push_back(Pair(sporkDef.name, sporkManager.IsSporkActive(sporkDef.sporkId))); } return ret; } @@ -291,8 +289,8 @@ UniValue spork(const JSONRPCRequest& request) + HelpExampleRpc("spork", "\"show\"")); } else { // advanced mode, update spork values - int nSporkID = sporkManager.GetSporkIDByName(request.params[0].get_str()); - if(nSporkID == -1) + SporkId nSporkID = sporkManager.GetSporkIDByName(request.params[0].get_str()); + if(nSporkID == SPORK_INVALID) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid spork name"); if (!g_connman) diff --git a/src/spork.cpp b/src/spork.cpp index 776b12b8826a..76f3df049697 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -13,25 +13,34 @@ #include -CSporkManager sporkManager; - const std::string CSporkManager::SERIALIZATION_VERSION_STRING = "CSporkManager-Version-2"; -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_9_SUPERBLOCKS_ENABLED, 4070908800ULL}, // OFF - {SPORK_12_RECONSIDER_BLOCKS, 0}, // 0 BLOCKS - {SPORK_15_DETERMINISTIC_MNS_ENABLED, 4070908800ULL}, // OFF - {SPORK_16_INSTANTSEND_AUTOLOCKS, 4070908800ULL}, // OFF - {SPORK_17_QUORUM_DKG_ENABLED, 4070908800ULL}, // OFF - {SPORK_19_CHAINLOCKS_ENABLED, 4070908800ULL}, // OFF - {SPORK_20_INSTANTSEND_LLMQ_BASED, 4070908800ULL}, // OFF +#define MAKE_SPORK_DEF(name, defaultValue) CSporkDef{name, defaultValue, #name} +std::vector sporkDefs = { + MAKE_SPORK_DEF(SPORK_2_INSTANTSEND_ENABLED, 0), // ON + MAKE_SPORK_DEF(SPORK_3_INSTANTSEND_BLOCK_FILTERING, 0), // ON + MAKE_SPORK_DEF(SPORK_5_INSTANTSEND_MAX_VALUE, 1000), // 1000 Dash + MAKE_SPORK_DEF(SPORK_6_NEW_SIGS, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_12_RECONSIDER_BLOCKS, 0), // 0 BLOCKS + MAKE_SPORK_DEF(SPORK_15_DETERMINISTIC_MNS_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_16_INSTANTSEND_AUTOLOCKS, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_17_QUORUM_DKG_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_19_CHAINLOCKS_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_20_INSTANTSEND_LLMQ_BASED, 4070908800ULL), // OFF }; -bool CSporkManager::SporkValueIsActive(int nSporkID, int64_t &nActiveValueRet) const +CSporkManager sporkManager; + +CSporkManager::CSporkManager() +{ + for (auto& sporkDef : sporkDefs) { + sporkDefsById.emplace(sporkDef.sporkId, &sporkDef); + sporkDefsByName.emplace(sporkDef.name, &sporkDef); + } +} + +bool CSporkManager::SporkValueIsActive(SporkId nSporkID, int64_t &nActiveValueRet) const { LOCK(cs); @@ -192,7 +201,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, const std::string& strCommand, CD } -void CSporkManager::ExecuteSpork(int nSporkID, int nValue) +void CSporkManager::ExecuteSpork(SporkId nSporkID, int nValue) { //correct fork via spork technology if(nSporkID == SPORK_12_RECONSIDER_BLOCKS && nValue > 0) { @@ -221,7 +230,7 @@ void CSporkManager::ExecuteSpork(int nSporkID, int nValue) } } -bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman) +bool CSporkManager::UpdateSpork(SporkId nSporkID, int64_t nValue, CConnman& connman) { CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetAdjustedTime()); @@ -244,24 +253,13 @@ bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman) return false; } -bool CSporkManager::IsSporkActive(int nSporkID) +bool CSporkManager::IsSporkActive(SporkId nSporkID) { - LOCK(cs); - int64_t nSporkValue = -1; - - if (SporkValueIsActive(nSporkID, nSporkValue)) { - return nSporkValue < GetAdjustedTime(); - } - - if (mapSporkDefaults.count(nSporkID)) { - return mapSporkDefaults[nSporkID] < GetAdjustedTime(); - } - - LogPrint(BCLog::SPORK, "CSporkManager::IsSporkActive -- Unknown Spork ID %d\n", nSporkID); - return false; + int64_t nSporkValue = GetSporkValue(nSporkID); + return nSporkValue < GetAdjustedTime(); } -int64_t CSporkManager::GetSporkValue(int nSporkID) +int64_t CSporkManager::GetSporkValue(SporkId nSporkID) { LOCK(cs); @@ -270,50 +268,33 @@ int64_t CSporkManager::GetSporkValue(int nSporkID) return nSporkValue; } - if (mapSporkDefaults.count(nSporkID)) { - return mapSporkDefaults[nSporkID]; + auto it = sporkDefsById.find(nSporkID); + if (it != sporkDefsById.end()) { + return it->second->defaultValue; } LogPrint(BCLog::SPORK, "CSporkManager::GetSporkValue -- Unknown Spork ID %d\n", nSporkID); return -1; } -int CSporkManager::GetSporkIDByName(const std::string& strName) +SporkId 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_9_SUPERBLOCKS_ENABLED") return SPORK_9_SUPERBLOCKS_ENABLED; - if (strName == "SPORK_12_RECONSIDER_BLOCKS") return SPORK_12_RECONSIDER_BLOCKS; - 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; - if (strName == "SPORK_19_CHAINLOCKS_ENABLED") return SPORK_19_CHAINLOCKS_ENABLED; - if (strName == "SPORK_20_INSTANTSEND_LLMQ_BASED") return SPORK_20_INSTANTSEND_LLMQ_BASED; - - LogPrint(BCLog::SPORK, "CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName); - return -1; + auto it = sporkDefsByName.find(strName); + if (it == sporkDefsByName.end()) { + LogPrint(BCLog::SPORK, "CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName); + return SPORK_INVALID; + } + return it->second->sporkId; } -std::string CSporkManager::GetSporkNameByID(int nSporkID) +std::string CSporkManager::GetSporkNameByID(SporkId nSporkID) { - switch (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_9_SUPERBLOCKS_ENABLED: return "SPORK_9_SUPERBLOCKS_ENABLED"; - case SPORK_12_RECONSIDER_BLOCKS: return "SPORK_12_RECONSIDER_BLOCKS"; - 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"; - case SPORK_19_CHAINLOCKS_ENABLED: return "SPORK_19_CHAINLOCKS_ENABLED"; - case SPORK_20_INSTANTSEND_LLMQ_BASED: return "SPORK_20_INSTANTSEND_LLMQ_BASED"; - default: - LogPrint(BCLog::SPORK, "CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID); - return "Unknown"; + auto it = sporkDefsById.find(nSporkID); + if (it == sporkDefsById.end()) { + LogPrint(BCLog::SPORK, "CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID); + return "Unknown"; } + return it->second->name; } bool CSporkManager::GetSporkByHash(const uint256& hash, CSporkMessage &sporkRet) diff --git a/src/spork.h b/src/spork.h index b28cc47a1cec..8e131f31d50f 100644 --- a/src/spork.h +++ b/src/spork.h @@ -20,22 +20,31 @@ class CSporkManager; Don't ever reuse these IDs for other sporks - This would result in old clients getting confused about which spork is for what */ -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_9_SUPERBLOCKS_ENABLED = 10008; -static const int SPORK_12_RECONSIDER_BLOCKS = 10011; -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; -static const int SPORK_19_CHAINLOCKS_ENABLED = 10018; -static const int SPORK_20_INSTANTSEND_LLMQ_BASED = 10019; - -static const int SPORK_START = SPORK_2_INSTANTSEND_ENABLED; -static const int SPORK_END = SPORK_20_INSTANTSEND_LLMQ_BASED; - -extern std::map mapSporkDefaults; +enum SporkId : int32_t { + SPORK_2_INSTANTSEND_ENABLED = 10001, + SPORK_3_INSTANTSEND_BLOCK_FILTERING = 10002, + SPORK_5_INSTANTSEND_MAX_VALUE = 10004, + SPORK_6_NEW_SIGS = 10005, + SPORK_9_SUPERBLOCKS_ENABLED = 10008, + SPORK_12_RECONSIDER_BLOCKS = 10011, + SPORK_15_DETERMINISTIC_MNS_ENABLED = 10014, + SPORK_16_INSTANTSEND_AUTOLOCKS = 10015, + SPORK_17_QUORUM_DKG_ENABLED = 10016, + SPORK_19_CHAINLOCKS_ENABLED = 10018, + SPORK_20_INSTANTSEND_LLMQ_BASED = 10019, + + SPORK_INVALID = -1, +}; +template<> struct is_serializable_enum : std::true_type {}; + +struct CSporkDef +{ + SporkId sporkId{SPORK_INVALID}; + int64_t defaultValue{0}; + std::string name; +}; + +extern std::vector sporkDefs; extern CSporkManager sporkManager; /** @@ -62,18 +71,18 @@ class CSporkMessage std::vector vchSig; public: - int nSporkID; + SporkId nSporkID; int64_t nValue; int64_t nTimeSigned; - CSporkMessage(int nSporkID, int64_t nValue, int64_t nTimeSigned) : + CSporkMessage(SporkId nSporkID, int64_t nValue, int64_t nTimeSigned) : nSporkID(nSporkID), nValue(nValue), nTimeSigned(nTimeSigned) {} CSporkMessage() : - nSporkID(0), + nSporkID((SporkId)0), nValue(0), nTimeSigned(0) {} @@ -137,9 +146,12 @@ class CSporkManager private: static const std::string SERIALIZATION_VERSION_STRING; + std::unordered_map sporkDefsById; + std::unordered_map sporkDefsByName; + mutable CCriticalSection cs; std::unordered_map mapSporksByHash; - std::unordered_map > mapSporksActive; + std::unordered_map > mapSporksActive; std::set setSporkPubKeyIDs; int nMinSporkKeys; @@ -149,11 +161,11 @@ class CSporkManager * SporkValueIsActive is used to get the value agreed upon by the majority * of signed spork messages for a given Spork ID. */ - bool SporkValueIsActive(int nSporkID, int64_t& nActiveValueRet) const; + bool SporkValueIsActive(SporkId nSporkID, int64_t& nActiveValueRet) const; public: - CSporkManager() {} + CSporkManager(); ADD_SERIALIZE_METHODS; @@ -209,13 +221,13 @@ class CSporkManager * * Currently only used with Spork 12. */ - void ExecuteSpork(int nSporkID, int nValue); + void ExecuteSpork(SporkId nSporkID, int nValue); /** * UpdateSpork is used by the spork RPC command to set a new spork value, sign * and broadcast the spork message. */ - bool UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman); + bool UpdateSpork(SporkId nSporkID, int64_t nValue, CConnman& connman); /** * IsSporkActive returns a bool for time-based sporks, and should be used @@ -226,23 +238,23 @@ class CSporkManager * instead, and therefore this method doesn't make sense and should not be * used. */ - bool IsSporkActive(int nSporkID); + bool IsSporkActive(SporkId nSporkID); /** * GetSporkValue returns the spork value given a Spork ID. If no active spork * message has yet been received by the node, it returns the default value. */ - int64_t GetSporkValue(int nSporkID); + int64_t GetSporkValue(SporkId nSporkID); /** * GetSporkIDByName returns the internal Spork ID given the spork name. */ - int GetSporkIDByName(const std::string& strName); + SporkId GetSporkIDByName(const std::string& strName); /** * GetSporkNameByID returns the spork name as a string, given a Spork ID. */ - std::string GetSporkNameByID(int nSporkID); + std::string GetSporkNameByID(SporkId nSporkID); /** * GetSporkByHash returns a spork message given a hash of the spork message. From e02c562aa53976f53a8367a50e0ba23491b05213 Mon Sep 17 00:00:00 2001 From: thephez Date: Wed, 29 May 2019 14:19:17 -0400 Subject: [PATCH 133/987] [RPC] Remove check for deprecated `masternode start-many` command (#2950) --- src/rpc/masternode.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 8734e0af87ee..32c3e5b3583b 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -444,11 +444,6 @@ UniValue masternode(const JSONRPCRequest& request) strCommand = request.params[0].get_str(); } -#ifdef ENABLE_WALLET - if (strCommand == "start-many") - throw JSONRPCError(RPC_INVALID_PARAMETER, "DEPRECATED, please use start-all instead"); -#endif // ENABLE_WALLET - if (request.fHelp && strCommand.empty()) { masternode_help(); } From d28d318aad694dd8819fdd458f017b537f664c9e Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 29 May 2019 21:19:53 +0300 Subject: [PATCH 134/987] Remove logic for handling objects and votes orphaned by not-yet-known MNs (#2954) This should no longer happen now that we use deterministic masternode list. --- src/dsnotificationinterface.cpp | 2 - src/governance/governance-object.cpp | 47 ++---------------- src/governance/governance-object.h | 7 +-- src/governance/governance.cpp | 71 ++-------------------------- src/governance/governance.h | 7 --- src/rpc/governance.cpp | 3 +- 6 files changed, 9 insertions(+), 128 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 2bd91ca87be4..8f2cb81f235a 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -116,8 +116,6 @@ void CDSNotificationInterface::BlockDisconnected(const std::shared_ptr= nAbsVoteReq) fCachedValid = false; } - -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()) { - bool fRemove = false; - const COutPoint& key = it->key; - const vote_time_pair_t& pairVote = it->value; - const CGovernanceVote& vote = pairVote.first; - if (pairVote.second < nNow) { - fRemove = true; - } else if (!mnList.HasValidMNByCollateral(vote.GetMasternodeOutpoint())) { - ++it; - continue; - } - CGovernanceException exception; - if (!ProcessVote(nullptr, vote, exception, connman)) { - LogPrintf("CGovernanceObject::CheckOrphanVotes -- Failed to add orphan vote: %s\n", exception.what()); - } else { - vote.Relay(connman); - fRemove = true; - } - ++it; - if (fRemove) { - cmmapOrphanVotes.Erase(key, pairVote); - } - } -} diff --git a/src/governance/governance-object.h b/src/governance/governance-object.h index 21659c275daf..99dbe0c4d6ef 100644 --- a/src/governance/governance-object.h +++ b/src/governance/governance-object.h @@ -180,9 +180,6 @@ class CGovernanceObject vote_m_t mapCurrentMNVotes; - /// Limited map of votes orphaned by MN - vote_cmm_t cmmapOrphanVotes; - CGovernanceObjectVoteFile fileVotes; public: @@ -267,7 +264,7 @@ class CGovernanceObject bool IsValidLocally(std::string& strError, bool fCheckCollateral) const; - bool IsValidLocally(std::string& strError, bool& fMissingMasternode, bool& fMissingConfirmations, bool fCheckCollateral) const; + bool IsValidLocally(std::string& strError, bool& fMissingConfirmations, bool fCheckCollateral) const; /// Check the collateral transaction for the budget proposal/finalized budget bool IsCollateralValid(std::string& strError, bool& fMissingConfirmations) const; @@ -350,8 +347,6 @@ class CGovernanceObject // also for MNs that were removed from the list completely. // Returns deleted vote hashes. std::set RemoveInvalidVotes(const COutPoint& mnOutpoint); - - void CheckOrphanVotes(CConnman& connman); }; diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index b5cb586c228a..7470f379f9a1 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -33,7 +33,6 @@ CGovernanceManager::CGovernanceManager() : nCachedBlockHeight(0), mapObjects(), mapErasedGovernanceObjects(), - mapMasternodeOrphanObjects(), cmapVoteToObject(MAX_CACHE_SIZE), cmapInvalidVotes(MAX_CACHE_SIZE), cmmapOrphanVotes(MAX_CACHE_SIZE), @@ -161,8 +160,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm LOCK2(cs_main, cs); - if (mapObjects.count(nHash) || mapPostponedObjects.count(nHash) || - mapErasedGovernanceObjects.count(nHash) || mapMasternodeOrphanObjects.count(nHash)) { + if (mapObjects.count(nHash) || mapPostponedObjects.count(nHash) || mapErasedGovernanceObjects.count(nHash)) { // TODO - print error code? what if it's GOVOBJ_ERROR_IMMATURE? LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Received already seen object: %s\n", strHash); return; @@ -177,11 +175,10 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm std::string strError = ""; // CHECK OBJECT AGAINST LOCAL BLOCKCHAIN - bool fMasternodeMissing = false; bool fMissingConfirmations = false; - bool fIsValid = govobj.IsValidLocally(strError, fMasternodeMissing, fMissingConfirmations, true); + bool fIsValid = govobj.IsValidLocally(strError, fMissingConfirmations, true); - if (fRateCheckBypassed && (fIsValid || fMasternodeMissing)) { + if (fRateCheckBypassed && fIsValid) { if (!MasternodeRateCheck(govobj, true)) { LogPrintf("MNGOVERNANCEOBJECT -- masternode rate check failed (after signature verification) - %s - (current block height %d)\n", strHash, nCachedBlockHeight); return; @@ -189,21 +186,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm } if (!fIsValid) { - if (fMasternodeMissing) { - int& count = mapMasternodeOrphanCounter[govobj.GetMasternodeOutpoint()]; - if (count >= 10) { - LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- Too many orphan objects, missing masternode=%s\n", govobj.GetMasternodeOutpoint().ToStringShort()); - // ask for this object again in 2 minutes - CInv inv(MSG_GOVERNANCE_OBJECT, govobj.GetHash()); - pfrom->AskFor(inv); - return; - } - - count++; - ExpirationInfo info(pfrom->GetId(), GetAdjustedTime() + GOVERNANCE_ORPHAN_EXPIRATION_TIME); - mapMasternodeOrphanObjects.insert(std::make_pair(nHash, object_info_pair_t(govobj, info))); - LogPrintf("MNGOVERNANCEOBJECT -- Missing masternode for: %s, strError = %s\n", strHash, strError); - } else if (fMissingConfirmations) { + if (fMissingConfirmations) { AddPostponedObject(govobj); LogPrintf("MNGOVERNANCEOBJECT -- Not enough fee confirmations for: %s, strError = %s\n", strHash, strError); } else { @@ -863,52 +846,6 @@ bool CGovernanceManager::ProcessVote(CNode* pfrom, const CGovernanceVote& vote, return fOk; } -void CGovernanceManager::CheckMasternodeOrphanVotes(CConnman& connman) -{ - LOCK2(cs_main, cs); - - ScopedLockBool guard(cs, fRateChecksEnabled, false); - - for (auto& objPair : mapObjects) { - objPair.second.CheckOrphanVotes(connman); - } -} - -void CGovernanceManager::CheckMasternodeOrphanObjects(CConnman& connman) -{ - LOCK2(cs_main, cs); - int64_t nNow = GetAdjustedTime(); - ScopedLockBool guard(cs, fRateChecksEnabled, false); - object_info_m_it it = mapMasternodeOrphanObjects.begin(); - while (it != mapMasternodeOrphanObjects.end()) { - object_info_pair_t& pair = it->second; - CGovernanceObject& govobj = pair.first; - - if (pair.second.nExpirationTime >= nNow) { - std::string strError; - bool fMasternodeMissing = false; - bool fConfirmationsMissing = false; - bool fIsValid = govobj.IsValidLocally(strError, fMasternodeMissing, fConfirmationsMissing, true); - - if (fIsValid) { - AddGovernanceObject(govobj, connman); - } else if (fMasternodeMissing) { - ++it; - continue; - } - } else { - // apply node's ban score - Misbehaving(pair.second.idFrom, 20); - } - - auto it_count = mapMasternodeOrphanCounter.find(govobj.GetMasternodeOutpoint()); - if (--it_count->second == 0) - mapMasternodeOrphanCounter.erase(it_count); - - mapMasternodeOrphanObjects.erase(it++); - } -} - void CGovernanceManager::CheckPostponedObjects(CConnman& connman) { if (!masternodeSync.IsSynced()) return; diff --git a/src/governance/governance.h b/src/governance/governance.h index e30a51b5cb02..d9031cca939e 100644 --- a/src/governance/governance.h +++ b/src/governance/governance.h @@ -241,9 +241,6 @@ class CGovernanceManager // value - expiration time for deleted objects hash_time_m_t mapErasedGovernanceObjects; - object_info_m_t mapMasternodeOrphanObjects; - txout_int_m_t mapMasternodeOrphanCounter; - object_m_t mapPostponedObjects; hash_s_t setAdditionalRelayObjects; @@ -402,10 +399,6 @@ class CGovernanceManager return fOK; } - void CheckMasternodeOrphanVotes(CConnman& connman); - - void CheckMasternodeOrphanObjects(CConnman& connman); - void CheckPostponedObjects(CConnman& connman); bool AreRateChecksEnabled() const diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index f9c23b60d9a6..16ea771ae28b 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -308,11 +308,10 @@ UniValue gobject_submit(const JSONRPCRequest& request) std::string strHash = govobj.GetHash().ToString(); std::string strError = ""; - bool fMissingMasternode; bool fMissingConfirmations; { LOCK(cs_main); - if (!govobj.IsValidLocally(strError, fMissingMasternode, fMissingConfirmations, true) && !fMissingConfirmations) { + if (!govobj.IsValidLocally(strError, fMissingConfirmations, true) && !fMissingConfirmations) { LogPrintf("gobject(submit) -- Object submission rejected because object is not valid - hash = %s, strError = %s\n", strHash, strError); throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + strHash + " - " + strError); } From 26bd0d278b0093f4a0ad6beb6120a78e204f7842 Mon Sep 17 00:00:00 2001 From: rikublock <46352032+rikublock@users.noreply.github.com> Date: Thu, 30 May 2019 10:00:07 +0200 Subject: [PATCH 135/987] Fix bls and bls_dkg bench (#2955) Properly start the blsWorker before running any BLS related benchmarks. --- src/bench/bench_dash.cpp | 2 ++ src/bench/bls.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/bench/bench_dash.cpp b/src/bench/bench_dash.cpp index 7d30af90c92e..2cb94af3cff2 100644 --- a/src/bench/bench_dash.cpp +++ b/src/bench/bench_dash.cpp @@ -11,6 +11,7 @@ #include "bls/bls.h" +void InitBLSTests(); void CleanupBLSTests(); void CleanupBLSDkgTests(); @@ -24,6 +25,7 @@ main(int argc, char** argv) ECCVerifyHandle verifyHandle; BLSInit(); + InitBLSTests(); SetupEnvironment(); fPrintToDebugLog = false; // don't want to write to debug.log file diff --git a/src/bench/bls.cpp b/src/bench/bls.cpp index 8127c2935a08..827af86d8100 100644 --- a/src/bench/bls.cpp +++ b/src/bench/bls.cpp @@ -11,6 +11,11 @@ CBLSWorker blsWorker; +void InitBLSTests() +{ + blsWorker.Start(); +} + void CleanupBLSTests() { blsWorker.Stop(); From 09d66c7764a53e06819068ea170cd5d0a1016d89 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 30 May 2019 11:00:31 +0300 Subject: [PATCH 136/987] Fix compiler warning (#2956) ``` ./serialize.h:762:49: warning: static_assert with no message is a C++17 extension [-Wc++17-extensions] static_assert(is_serializable_enum::value); ^ , "" ``` --- src/serialize.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/serialize.h b/src/serialize.h index 268c70396f99..6afb0677d445 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -748,7 +748,7 @@ template::v inline void Serialize(Stream& s, T a ) { // If you ever get into this situation, it usaully means you forgot to declare is_serializable_enum for the desired enum type - static_assert(is_serializable_enum::value); + static_assert(is_serializable_enum::value, "Missing declararion of is_serializable_enum"); typedef typename std::underlying_type::type T2; T2 b = (T2)a; @@ -759,7 +759,7 @@ template::v inline void Unserialize(Stream& s, T& a ) { // If you ever get into this situation, it usaully means you forgot to declare is_serializable_enum for the desired enum type - static_assert(is_serializable_enum::value); + static_assert(is_serializable_enum::value, "Missing declararion of is_serializable_enum"); typedef typename std::underlying_type::type T2; T2 b; From 809aae73a1175fa9b0e69fd988879868ee497eb5 Mon Sep 17 00:00:00 2001 From: thephez Date: Thu, 30 May 2019 04:01:16 -0400 Subject: [PATCH 137/987] RPC docs helper updates (#2949) * RPC - Update gobject description to match other multi-command RPCs * RPC - Update masternodelist to avoid returning dupe RPC name from help * RPC - Make spacing consistent in gobject/masternode help --- src/rpc/governance.cpp | 4 ++-- src/rpc/masternode.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 16ea771ae28b..9e3f695bed08 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -871,8 +871,8 @@ UniValue gobject_getcurrentvotes(const JSONRPCRequest& request) [[ noreturn ]] void gobject_help() { throw std::runtime_error( - "gobject \"command\"...\n" - "Manage governance objects\n" + "gobject \"command\" ...\n" + "Set of commands to manage governance objects.\n" "\nAvailable commands:\n" " check - Validate governance object data (proposal only)\n" #ifdef ENABLE_WALLET diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 32c3e5b3583b..24ef9e22b9b2 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -125,8 +125,8 @@ UniValue getpoolinfo(const JSONRPCRequest& request) void masternode_list_help() { throw std::runtime_error( - "masternode list ( \"mode\" \"filter\" )\n" - "Get a list of masternodes in different modes. This call is identical to masternodelist call.\n" + "masternodelist ( \"mode\" \"filter\" )\n" + "Get a list of masternodes in different modes. This call is identical to 'masternode list' call.\n" "\nArguments:\n" "1. \"mode\" (string, optional/required to use filter, defaults = json) The mode to run list in\n" "2. \"filter\" (string, optional) Filter results. Partial match by outpoint by default in all modes,\n" @@ -420,7 +420,7 @@ UniValue masternode_winners(const JSONRPCRequest& request) [[ noreturn ]] void masternode_help() { throw std::runtime_error( - "masternode \"command\"...\n" + "masternode \"command\" ...\n" "Set of commands to execute masternode related actions\n" "\nArguments:\n" "1. \"command\" (string or set of strings, required) The command to execute\n" From ebded7d833e46b6d4a8fef40f19871e315cfffbb Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 4 Jun 2019 01:35:58 +0300 Subject: [PATCH 138/987] Update help text via gen-manpages.sh --- doc/man/dash-cli.1 | 8 +++--- doc/man/dash-qt.1 | 67 +++++++++++++++++++++++++--------------------- doc/man/dash-tx.1 | 8 +++--- doc/man/dashd.1 | 67 +++++++++++++++++++++++++--------------------- 4 files changed, 80 insertions(+), 70 deletions(-) diff --git a/doc/man/dash-cli.1 b/doc/man/dash-cli.1 index ce3755ed2101..579c1700a41e 100644 --- a/doc/man/dash-cli.1 +++ b/doc/man/dash-cli.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH DASH-CLI "1" "May 2019" "dash-cli v0.14.0.1" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10. +.TH DASH-CLI "1" "June 2019" "dash-cli v0.14.1.0" "User Commands" .SH NAME -dash-cli \- manual page for dash-cli v0.14.0.1 +dash-cli \- manual page for dash-cli v0.14.1.0 .SH DESCRIPTION -Dash Core RPC client version v0.14.0.1 +Dash Core RPC client version v0.14.1.0 .SS "Usage:" .TP dash\-cli [options] [params] diff --git a/doc/man/dash-qt.1 b/doc/man/dash-qt.1 index 0b32a141f7b1..648ae0a3ae2e 100644 --- a/doc/man/dash-qt.1 +++ b/doc/man/dash-qt.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH DASH-QT "1" "May 2019" "dash-qt v0.14.0.1" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10. +.TH DASH-QT "1" "June 2019" "dash-qt v0.14.1.0" "User Commands" .SH NAME -dash-qt \- manual page for dash-qt v0.14.0.1 +dash-qt \- manual page for dash-qt v0.14.1.0 .SH DESCRIPTION -Dash Core version v0.14.0.1 (64\-bit) +Dash Core version v0.14.1.0 (64\-bit) Usage: .IP dash\-qt [command\-line options] @@ -76,7 +76,7 @@ Extra transactions to keep in memory for compact block reconstructions .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-2\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR @@ -154,8 +154,8 @@ for IPv6 .HP \fB\-connect=\fR .IP -Connect only to the specified node(s); \fB\-noconnect\fR or \fB\-connect\fR=\fI\,0\/\fR alone to -disable automatic connections +Connect only to the specified node(s); \fB\-connect\fR=\fI\,0\/\fR disables automatic +connections .HP \fB\-discover\fR .IP @@ -169,7 +169,7 @@ Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (def \fB\-dnsseed\fR .IP Query for peer addresses via DNS lookup, if low on addresses (default: 1 -unless \fB\-connect\fR/\-noconnect) +unless \fB\-connect\fR used) .HP \fB\-externalip=\fR .IP @@ -181,8 +181,7 @@ Always query for peer addresses via DNS lookup (default: 0) .HP \fB\-listen\fR .IP -Accept connections from outside (default: 1 if no \fB\-proxy\fR or -\fB\-connect\fR/\-noconnect) +Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR) .HP \fB\-listenonion\fR .IP @@ -272,16 +271,6 @@ times. Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway .HP -\fB\-whitelistrelay\fR -.IP -Accept relayed transactions received from whitelisted peers even when -not relaying transactions (default: 1) -.HP -\fB\-whitelistforcerelay\fR -.IP -Force relay of transactions from whitelisted peers even if they violate -local relay policy (default: 1) -.HP \fB\-maxuploadtarget=\fR .IP Tries to keep outbound traffic under the given target (in MiB per 24h), @@ -459,12 +448,18 @@ Append comment to the user agent string .IP Output debugging information (default: 0, supplying is optional). If is not supplied or if = 1, -output all debugging information. can be: addrman, -alert, bench, cmpctblock, coindb, db, http, leveldb, libevent, -lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, -selectcoins, tor, zmq, dash (or specifically: chainlocks, -gobject, instantsend, keepass, llmq, llmq\-dkg, llmq\-sigs, -masternode, mnpayments, mnsync, privatesend, spork), qt. +output all debugging information. can be: net, tor, +mempool, http, bench, zmq, db, rpc, estimatefee, addrman, +selectcoins, reindex, cmpctblock, rand, prune, proxy, mempoolrej, +libevent, coindb, qt, leveldb, chainlocks, gobject, instantsend, +keepass, llmq, llmq\-dkg, llmq\-sigs, mnpayments, mnsync, +privatesend, spork, alert. +.HP +\fB\-debugexclude=\fR +.IP +Exclude debugging information for a category. Can be used in conjunction +with \fB\-debug\fR=\fI\,1\/\fR to output debug logs for all categories except one +or more specified categories. .HP \fB\-help\-debug\fR .IP @@ -478,11 +473,6 @@ Include IP addresses in debug output (default: 0) .IP Prepend debug output with timestamp (default: 1) .HP -\fB\-minrelaytxfee=\fR -.IP -Fees (in DASH/kB) smaller than this are considered zero fee for -relaying, mining and transaction creation (default: 0.00001) -.HP \fB\-maxtxfee=\fR .IP Maximum total fees (in DASH) to use in a single wallet transaction or @@ -599,6 +589,21 @@ Relay and mine data carrier transactions (default: 1) .IP Maximum size of data in data carrier transactions we relay and mine (default: 83) +.HP +\fB\-minrelaytxfee=\fR +.IP +Fees (in DASH/kB) smaller than this are considered zero fee for +relaying, mining and transaction creation (default: 0.00001) +.HP +\fB\-whitelistrelay\fR +.IP +Accept relayed transactions received from whitelisted peers even when +not relaying transactions (default: 1) +.HP +\fB\-whitelistforcerelay\fR +.IP +Force relay of transactions from whitelisted peers even if they violate +local relay policy (default: 1) .PP Block creation options: .HP diff --git a/doc/man/dash-tx.1 b/doc/man/dash-tx.1 index f837b7aae660..d4ecd6b3c832 100644 --- a/doc/man/dash-tx.1 +++ b/doc/man/dash-tx.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH DASH-TX "1" "May 2019" "dash-tx v0.14.0.1" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10. +.TH DASH-TX "1" "June 2019" "dash-tx v0.14.1.0" "User Commands" .SH NAME -dash-tx \- manual page for dash-tx v0.14.0.1 +dash-tx \- manual page for dash-tx v0.14.1.0 .SH DESCRIPTION -Dash Core dash\-tx utility version v0.14.0.1 +Dash Core dash\-tx utility version v0.14.1.0 .SS "Usage:" .TP dash\-tx [options] [commands] diff --git a/doc/man/dashd.1 b/doc/man/dashd.1 index 8cd59757c34d..1f2d9b8fcbbd 100644 --- a/doc/man/dashd.1 +++ b/doc/man/dashd.1 @@ -1,9 +1,9 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4. -.TH DASHD "1" "May 2019" "dashd v0.14.0.1" "User Commands" +.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10. +.TH DASHD "1" "June 2019" "dashd v0.14.1.0" "User Commands" .SH NAME -dashd \- manual page for dashd v0.14.0.1 +dashd \- manual page for dashd v0.14.1.0 .SH DESCRIPTION -Dash Core Daemon version v0.14.0.1 +Dash Core Daemon version v0.14.1.0 .SS "Usage:" .TP dashd [options] @@ -81,7 +81,7 @@ Extra transactions to keep in memory for compact block reconstructions .HP \fB\-par=\fR .IP -Set the number of script verification threads (\fB\-4\fR to 16, 0 = auto, <0 = +Set the number of script verification threads (\fB\-2\fR to 16, 0 = auto, <0 = leave that many cores free, default: 0) .HP \fB\-pid=\fR @@ -159,8 +159,8 @@ for IPv6 .HP \fB\-connect=\fR .IP -Connect only to the specified node(s); \fB\-noconnect\fR or \fB\-connect\fR=\fI\,0\/\fR alone to -disable automatic connections +Connect only to the specified node(s); \fB\-connect\fR=\fI\,0\/\fR disables automatic +connections .HP \fB\-discover\fR .IP @@ -174,7 +174,7 @@ Allow DNS lookups for \fB\-addnode\fR, \fB\-seednode\fR and \fB\-connect\fR (def \fB\-dnsseed\fR .IP Query for peer addresses via DNS lookup, if low on addresses (default: 1 -unless \fB\-connect\fR/\-noconnect) +unless \fB\-connect\fR used) .HP \fB\-externalip=\fR .IP @@ -186,8 +186,7 @@ Always query for peer addresses via DNS lookup (default: 0) .HP \fB\-listen\fR .IP -Accept connections from outside (default: 1 if no \fB\-proxy\fR or -\fB\-connect\fR/\-noconnect) +Accept connections from outside (default: 1 if no \fB\-proxy\fR or \fB\-connect\fR) .HP \fB\-listenonion\fR .IP @@ -277,16 +276,6 @@ times. Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway .HP -\fB\-whitelistrelay\fR -.IP -Accept relayed transactions received from whitelisted peers even when -not relaying transactions (default: 1) -.HP -\fB\-whitelistforcerelay\fR -.IP -Force relay of transactions from whitelisted peers even if they violate -local relay policy (default: 1) -.HP \fB\-maxuploadtarget=\fR .IP Tries to keep outbound traffic under the given target (in MiB per 24h), @@ -460,12 +449,18 @@ Append comment to the user agent string .IP Output debugging information (default: 0, supplying is optional). If is not supplied or if = 1, -output all debugging information. can be: addrman, -alert, bench, cmpctblock, coindb, db, http, leveldb, libevent, -lock, mempool, mempoolrej, net, proxy, prune, rand, reindex, rpc, -selectcoins, tor, zmq, dash (or specifically: chainlocks, -gobject, instantsend, keepass, llmq, llmq\-dkg, llmq\-sigs, -masternode, mnpayments, mnsync, privatesend, spork). +output all debugging information. can be: net, tor, +mempool, http, bench, zmq, db, rpc, estimatefee, addrman, +selectcoins, reindex, cmpctblock, rand, prune, proxy, mempoolrej, +libevent, coindb, qt, leveldb, chainlocks, gobject, instantsend, +keepass, llmq, llmq\-dkg, llmq\-sigs, mnpayments, mnsync, +privatesend, spork, alert. +.HP +\fB\-debugexclude=\fR +.IP +Exclude debugging information for a category. Can be used in conjunction +with \fB\-debug\fR=\fI\,1\/\fR to output debug logs for all categories except one +or more specified categories. .HP \fB\-help\-debug\fR .IP @@ -479,11 +474,6 @@ Include IP addresses in debug output (default: 0) .IP Prepend debug output with timestamp (default: 1) .HP -\fB\-minrelaytxfee=\fR -.IP -Fees (in DASH/kB) smaller than this are considered zero fee for -relaying, mining and transaction creation (default: 0.00001) -.HP \fB\-maxtxfee=\fR .IP Maximum total fees (in DASH) to use in a single wallet transaction or @@ -600,6 +590,21 @@ Relay and mine data carrier transactions (default: 1) .IP Maximum size of data in data carrier transactions we relay and mine (default: 83) +.HP +\fB\-minrelaytxfee=\fR +.IP +Fees (in DASH/kB) smaller than this are considered zero fee for +relaying, mining and transaction creation (default: 0.00001) +.HP +\fB\-whitelistrelay\fR +.IP +Accept relayed transactions received from whitelisted peers even when +not relaying transactions (default: 1) +.HP +\fB\-whitelistforcerelay\fR +.IP +Force relay of transactions from whitelisted peers even if they violate +local relay policy (default: 1) .PP Block creation options: .HP From 2c5e2bc6c8505ccef5fe7ef2805c25b33bfee263 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sat, 8 Jun 2019 14:16:20 +0300 Subject: [PATCH 139/987] Inject custom specialization of std::hash for SporkId enum into std (#2960) This should fix compilation on gcc5 --- src/spork.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/spork.h b/src/spork.h index 8e131f31d50f..1ba09bea839c 100644 --- a/src/spork.h +++ b/src/spork.h @@ -37,6 +37,17 @@ enum SporkId : int32_t { }; template<> struct is_serializable_enum : std::true_type {}; +namespace std +{ + template<> struct hash + { + std::size_t operator()(SporkId const& id) const noexcept + { + return std::hash{}(id); + } + }; +} + struct CSporkDef { SporkId sporkId{SPORK_INVALID}; From 85c9ea400b402dfcfa6b8b6141ace7c1dbe74f77 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sat, 8 Jun 2019 14:16:41 +0300 Subject: [PATCH 140/987] Throw a bit more descriptive error message on UpgradeDB failure on pruned nodes (#2962) --- src/llmq/quorums_blockprocessor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index 302600fe6a04..e7ddde295791 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -271,6 +271,10 @@ void CQuorumBlockProcessor::UpgradeDB() if (chainActive.Height() >= Params().GetConsensus().DIP0003EnforcementHeight) { auto pindex = chainActive[Params().GetConsensus().DIP0003EnforcementHeight]; while (pindex) { + if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) { + // Too late, we already pruned blocks we needed to reprocess commitments + throw std::runtime_error(std::string(__func__) + ": Quorum Commitments DB upgrade failed, you need to re-download the blockchain"); + } CBlock block; bool r = ReadBlockFromDisk(block, pindex, Params().GetConsensus()); assert(r); From a83b63186b390bf5081d3bbea7bc3177a1c119c8 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Sat, 8 Jun 2019 14:17:56 +0300 Subject: [PATCH 141/987] Fix UI masternode list (#2966) NotifyMasternodeListChanged is called before the tip is updated which means we can't rely on GetListAtChainTip() and have to pass the list into CClientUIInterface --- src/evo/deterministicmns.cpp | 4 ++-- src/qt/clientmodel.cpp | 8 ++++---- src/ui_interface.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index a00341851fdf..0cfaab4e3fab 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -505,7 +505,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde // Don't hold cs while calling signals if (diff.HasChanges()) { GetMainSignals().NotifyMasternodeListChanged(false, oldList, diff); - uiInterface.NotifyMasternodeListChanged(); + uiInterface.NotifyMasternodeListChanged(newList); } if (nHeight == consensusParams.DIP0003EnforcementHeight) { @@ -550,7 +550,7 @@ bool CDeterministicMNManager::UndoBlock(const CBlock& block, const CBlockIndex* if (diff.HasChanges()) { auto inversedDiff = curList.BuildDiff(prevList); GetMainSignals().NotifyMasternodeListChanged(true, curList, inversedDiff); - uiInterface.NotifyMasternodeListChanged(); + uiInterface.NotifyMasternodeListChanged(prevList); } const auto& consensusParams = Params().GetConsensus(); diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 0a636c476d06..9dec98682d9f 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -364,14 +364,14 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB } } -static void NotifyMasternodeListChanged(ClientModel *clientmodel) +static void NotifyMasternodeListChanged(ClientModel *clientmodel, const CDeterministicMNList& newList) { static int64_t nLastMasternodeUpdateNotification = 0; int64_t now = GetTimeMillis(); // if we are in-sync, update the UI regardless of last update time // no need to refresh masternode list/stats as often as blocks etc. if (masternodeSync.IsBlockchainSynced() || now - nLastMasternodeUpdateNotification > MODEL_UPDATE_DELAY*4*5) { - clientmodel->refreshMasternodeList(); + clientmodel->setMasternodeList(newList); nLastMasternodeUpdateNotification = now; } } @@ -392,7 +392,7 @@ void ClientModel::subscribeToCoreSignals() uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this)); uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2, false)); uiInterface.NotifyHeaderTip.connect(boost::bind(BlockTipChanged, this, _1, _2, true)); - uiInterface.NotifyMasternodeListChanged.connect(boost::bind(NotifyMasternodeListChanged, this)); + uiInterface.NotifyMasternodeListChanged.connect(boost::bind(NotifyMasternodeListChanged, this, _1)); uiInterface.NotifyAdditionalDataSyncProgressChanged.connect(boost::bind(NotifyAdditionalDataSyncProgressChanged, this, _1)); } @@ -406,6 +406,6 @@ void ClientModel::unsubscribeFromCoreSignals() uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this)); uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, false)); uiInterface.NotifyHeaderTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, true)); - uiInterface.NotifyMasternodeListChanged.disconnect(boost::bind(NotifyMasternodeListChanged, this)); + uiInterface.NotifyMasternodeListChanged.disconnect(boost::bind(NotifyMasternodeListChanged, this, _1)); uiInterface.NotifyAdditionalDataSyncProgressChanged.disconnect(boost::bind(NotifyAdditionalDataSyncProgressChanged, this, _1)); } diff --git a/src/ui_interface.h b/src/ui_interface.h index 98c882d63393..9d5ad977ee6b 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -111,7 +111,7 @@ class CClientUIInterface boost::signals2::signal NotifyHeaderTip; /** Masternode list has changed */ - boost::signals2::signal NotifyMasternodeListChanged; + boost::signals2::signal NotifyMasternodeListChanged; /** Additional data sync progress changed */ boost::signals2::signal NotifyAdditionalDataSyncProgressChanged; From 3d46bd3e79ade518b3a3842f3f1f17ce91045180 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 20 Apr 2017 23:06:56 +0200 Subject: [PATCH 142/987] Merge #10181: Include cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1c897fc Missing includes (Jorge Timón) a1fd450 Trivial: Remove unneeded includes from .h: (Jorge Timón) Tree-SHA512: ada3e62cc2435e58172a88b380be371b717a05725956c15e5493b6e19fe2903e5e6e43fd22dc24699333a0e8a0c7b42eb1ae61b41cb4ba82495be18e2d4ef3c6 move "#include "chain.h"" down a line Signed-off-by: Pasta --- src/checkqueue.h | 2 ++ src/coins.h | 1 + src/net.h | 1 - src/policy/policy.cpp | 1 + src/qt/clientmodel.cpp | 1 + src/qt/walletmodel.cpp | 1 + src/rpc/misc.cpp | 1 + src/validation.cpp | 1 + src/validation.h | 1 - src/wallet/rpcwallet.cpp | 1 + src/zmq/zmqpublishnotifier.cpp | 1 + 11 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/checkqueue.h b/src/checkqueue.h index ea12df66dd0e..63c104c02a11 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -5,6 +5,8 @@ #ifndef BITCOIN_CHECKQUEUE_H #define BITCOIN_CHECKQUEUE_H +#include "sync.h" + #include #include diff --git a/src/coins.h b/src/coins.h index faa7632b347a..eef64dc22f70 100644 --- a/src/coins.h +++ b/src/coins.h @@ -6,6 +6,7 @@ #ifndef BITCOIN_COINS_H #define BITCOIN_COINS_H +#include "primitives/transaction.h" #include "compressor.h" #include "core_memusage.h" #include "hash.h" diff --git a/src/net.h b/src/net.h index 694ed56a1f85..8d2904990427 100644 --- a/src/net.h +++ b/src/net.h @@ -52,7 +52,6 @@ #define DEFAULT_ALLOW_OPTIMISTIC_SEND false #endif -class CAddrMan; class CScheduler; class CNode; diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index eb41ad17053c..53347b5ff27f 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -8,6 +8,7 @@ #include "policy/policy.h" #include "validation.h" +#include "coins.h" #include "tinyformat.h" #include "util.h" #include "utilstrencodings.h" diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 0a636c476d06..bc3f2e60be1f 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -11,6 +11,7 @@ #include "peertablemodel.h" #include "alert.h" +#include "chain.h" #include "chainparams.h" #include "checkpoints.h" #include "clientversion.h" diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index ca518b8ceb9f..080b9a92dce3 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -14,6 +14,7 @@ #include "transactiontablemodel.h" #include "base58.h" +#include "chain.h" #include "keystore.h" #include "validation.h" #include "net.h" // for g_connman diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 779527971293..159273cbe1c7 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -5,6 +5,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "base58.h" +#include "chain.h" #include "clientversion.h" #include "init.h" #include "net.h" diff --git a/src/validation.cpp b/src/validation.cpp index caf93eee8723..efee26789e8c 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -9,6 +9,7 @@ #include "alert.h" #include "arith_uint256.h" #include "blockencodings.h" +#include "chain.h" #include "chainparams.h" #include "checkpoints.h" #include "checkqueue.h" diff --git a/src/validation.h b/src/validation.h index cab4ed6c1686..a0921302eb2a 100644 --- a/src/validation.h +++ b/src/validation.h @@ -12,7 +12,6 @@ #endif #include "amount.h" -#include "chain.h" #include "coins.h" #include "fs.h" #include "protocol.h" // For CMessageHeader::MessageStartChars diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 9f29f45238ea..49c1c119a359 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -10,6 +10,7 @@ #include "consensus/validation.h" #include "core_io.h" #include "init.h" +#include "wallet/coincontrol.h" #include "instantsend.h" #include "net.h" #include "policy/fees.h" diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 6134fde4a986..44bb9b9b4a93 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "chain.h" #include "chainparams.h" #include "streams.h" #include "zmqpublishnotifier.h" From 7cf74ddbc444a4ea25d21e701ea5884d022bb5a0 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 21 Apr 2017 10:56:44 +0200 Subject: [PATCH 143/987] Merge #10239: Make Boost use std::atomic internally 394ccf7 Make Boost use std::atomic internally (Pieter Wuille) Tree-SHA512: 2be198caea1b255d29ab841ca9f6ee4f32ec875cb9657553ed6ea6d21a4cd1390f1e3b22b23a3a4a24d9efc0bda100c7fbfd4dc480e0cc9831b565e989a2b636 --- configure.ac | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/configure.ac b/configure.ac index 2a820ec34561..30525e87dd4c 100644 --- a/configure.ac +++ b/configure.ac @@ -721,6 +721,10 @@ AX_BOOST_PROGRAM_OPTIONS AX_BOOST_THREAD AX_BOOST_CHRONO +dnl Boost 1.56 through 1.62 allow using std::atomic instead of its own atomic +dnl counter implementations. In 1.63 and later the std::atomic approach is default. +m4_pattern_allow(DBOOST_AC_USE_STD_ATOMIC) dnl otherwise it's treated like a macro +BOOST_CPPFLAGS="-DBOOST_SP_USE_STD_ATOMIC -DBOOST_AC_USE_STD_ATOMIC $BOOST_CPPFLAGS" if test x$use_reduce_exports = xyes; then AC_MSG_CHECKING([for working boost reduced exports]) From 6fb2866868bd29062d67339289dcf5b24cf9ab32 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 21 Apr 2017 17:12:12 +0200 Subject: [PATCH 144/987] Merge #10229: Tests: Add test for getdifficulty 821dd5e Tests: Add test for getdifficulty (Jimmy Song) Tree-SHA512: 3da78c4f88efdaab8374582cda606620beb2f1e9a93119a72b67572702c17c36b68c3abf9d466e8c7fb8ba9e8afa9a172e454c553df10d3054f19b3282d3097b --- test/functional/blockchain.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 3472841c1795..a8a497a2383b 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -6,6 +6,10 @@ Test the following RPCs: - gettxoutsetinfo + - getdifficulty + - getbestblockhash + - getblockhash + - getblockheader - verifychain Tests correspond to code in rpc/blockchain.cpp. @@ -39,6 +43,7 @@ def setup_network(self, split=False): def run_test(self): self._test_gettxoutsetinfo() self._test_getblockheader() + self._test_getdifficulty() self.nodes[0].verifychain(4, 0) def _test_gettxoutsetinfo(self): @@ -81,7 +86,8 @@ def _test_gettxoutsetinfo(self): def _test_getblockheader(self): node = self.nodes[0] - assert_raises_jsonrpc(-5, "Block not found", node.getblockheader, "nonsense") + assert_raises_jsonrpc(-5, "Block not found", + node.getblockheader, "nonsense") besthash = node.getbestblockhash() secondbesthash = node.getblockhash(199) @@ -103,5 +109,11 @@ def _test_getblockheader(self): assert isinstance(int(header['versionHex'], 16), int) assert isinstance(header['difficulty'], Decimal) + def _test_getdifficulty(self): + difficulty = self.nodes[0].getdifficulty() + # 1 hash in 2 should be valid, so difficulty should be 1/2**31 + # binary => decimal => binary math is why we do this check + assert abs(difficulty * 2**31 - 1) < 0.0001 + if __name__ == '__main__': BlockchainTest().main() From 14cbf547cc31d1b8c56165e79b5bf92c40b32497 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 23 Apr 2017 17:43:00 +0200 Subject: [PATCH 145/987] Merge #10023: [tests] remove maxblocksinflight.py (functionality covered by other test) 5f4bcf2 [tests] Remove maxblocksinflight testcase (John Newbery) Tree-SHA512: 827c8b12f4b52684a973bbfc508c5906e640572e22a96b9420a7aea86ad8d4aa4d6fcc2bb091f747e2fdd18c897e0456baff254bd5e3ceaf721bd3f09a2fd60b delete maxblocksinflight.py Signed-off-by: Pasta --- test/functional/README.md | 2 +- test/functional/maxblocksinflight.py | 93 ---------------------------- test/functional/test_runner.py | 1 - 3 files changed, 1 insertion(+), 95 deletions(-) delete mode 100755 test/functional/maxblocksinflight.py diff --git a/test/functional/README.md b/test/functional/README.md index 651b01f18a47..e6c4849702c7 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -59,7 +59,7 @@ thread.) * RPC calls are available in p2p tests. * Can be used to write free-form tests, where specific p2p-protocol behavior -is tested. Examples: ```p2p-accept-block.py```, ```maxblocksinflight.py```. +is tested. Examples: ```p2p-accept-block.py```, ```p2p-compactblocks.py```. ## Comptool diff --git a/test/functional/maxblocksinflight.py b/test/functional/maxblocksinflight.py deleted file mode 100755 index 99ffea90eeae..000000000000 --- a/test/functional/maxblocksinflight.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2015-2016 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test nodes responses to having many blocks in flight. - -In this test we connect to one node over p2p, send it numerous inv's, and -compare the resulting number of getdata requests to a max allowed value. We -test for exceeding 128 blocks in flight, which was the limit an 0.9 client will -reach. [0.10 clients shouldn't request more than 16 from a single peer.] -""" - -from test_framework.mininode import * -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * - -MAX_REQUESTS = 128 - -class TestManager(NodeConnCB): - def on_getdata(self, conn, message): - self.log.debug("got getdata %s" % repr(message)) - # Log the requests - for inv in message.inv: - if inv.hash not in self.blockReqCounts: - self.blockReqCounts[inv.hash] = 0 - self.blockReqCounts[inv.hash] += 1 - - def on_close(self, conn): - if not self.disconnectOkay: - raise EarlyDisconnectError(0) - - def add_new_connection(self, connection): - super().add_connection(connection) - self.blockReqCounts = {} - self.disconnectOkay = False - - def run(self): - self.connection.rpc.generate(1) # Leave IBD - - numBlocksToGenerate = [8, 16, 128, 1024] - for count in range(len(numBlocksToGenerate)): - current_invs = [] - for i in range(numBlocksToGenerate[count]): - current_invs.append(CInv(2, random.randrange(0, 1 << 256))) - if len(current_invs) >= 50000: - self.connection.send_message(msg_inv(current_invs)) - current_invs = [] - if len(current_invs) > 0: - self.connection.send_message(msg_inv(current_invs)) - - # Wait and see how many blocks were requested - time.sleep(2) - - total_requests = 0 - with mininode_lock: - for key in self.blockReqCounts: - total_requests += self.blockReqCounts[key] - if self.blockReqCounts[key] > 1: - raise AssertionError("Error, test failed: block %064x requested more than once" % key) - if total_requests > MAX_REQUESTS: - raise AssertionError("Error, too many blocks (%d) requested" % total_requests) - self.log.info("Round %d: success (total requests: %d)" % (count, total_requests)) - - self.disconnectOkay = True - self.connection.disconnect_node() - - -class MaxBlocksInFlightTest(BitcoinTestFramework): - def add_options(self, parser): - parser.add_option("--testbinary", dest="testbinary", - default=os.getenv("BITCOIND", "dashd"), - help="Binary to test max block requests behavior") - - def __init__(self): - super().__init__() - self.setup_clean_chain = True - self.num_nodes = 1 - - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1']], - binary=[self.options.testbinary]) - - def run_test(self): - test = TestManager() - # pass log handler through to the test manager object - test.log = self.log - test.add_new_connection(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test)) - NetworkThread().start() # Start up network handling in another thread - test.run() - -if __name__ == '__main__': - MaxBlocksInFlightTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 13eb97bcdaa3..84fc2c891a1f 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -136,7 +136,6 @@ 'txindex.py', 'forknotify.py', 'invalidateblock.py', - 'maxblocksinflight.py', 'p2p-acceptblock.py', # NOTE: needs dash_hash to pass ] From 83d0637f2d892a441dd546de316174d529a00b8d Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 23 Apr 2017 17:53:43 +0200 Subject: [PATCH 146/987] Merge #10097: Move zmq test skipping logic into individual test case. 6803e09 Move zmq test skipping logic into individual test case. (John Newbery) Tree-SHA512: 9d166b53e9acf386c4dafc860b38e2901b331a7505bba9714a2f4e3bdef68b0316c8b76fddbfb620835ddee549cf32fffb3a96a19b0799ad94f2553f55f19a35 s/bitcoind/dashd/ Signed-off-by: Pasta --- test/functional/test_runner.py | 25 ++++--------------------- test/functional/zmq_test.py | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 84fc2c891a1f..31eca769719b 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -64,6 +64,7 @@ 'rawtransactions.py', 'reindex.py', # vv Tests less than 30s vv + "zmq_test.py", 'mempool_resurrect_test.py', 'txn_doublespend.py --mineblock', 'txn_clone.py', @@ -103,11 +104,6 @@ 'p2p-fingerprint.py', ] -ZMQ_SCRIPTS = [ - # ZMQ test can only be run if Dash Core was built with zmq-enabled. - # call test_runner.py with -nozmq to explicitly exclude these tests. - 'zmq_test.py'] - EXTENDED_SCRIPTS = [ # These tests are not run by the travis build process. # Longest test should go first, to favor running tests in parallel @@ -140,7 +136,7 @@ ] # Place EXTENDED_SCRIPTS first since it has the 3 longest running tests -ALL_SCRIPTS = EXTENDED_SCRIPTS + BASE_SCRIPTS + ZMQ_SCRIPTS +ALL_SCRIPTS = EXTENDED_SCRIPTS + BASE_SCRIPTS NON_SCRIPTS = [ # These are python files that live in the functional tests directory, but are not test scripts. @@ -163,7 +159,6 @@ def main(): parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).') parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit') parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.') - parser.add_argument('--nozmq', action='store_true', help='do not run the zmq tests') args, unknown_args = parser.parse_known_args() # Create a set to store arguments and create the passon string @@ -177,7 +172,6 @@ def main(): enable_wallet = config["components"].getboolean("ENABLE_WALLET") enable_utils = config["components"].getboolean("ENABLE_UTILS") enable_bitcoind = config["components"].getboolean("ENABLE_BITCOIND") - enable_zmq = config["components"].getboolean("ENABLE_ZMQ") and not args.nozmq if config["environment"]["EXEEXT"] == ".exe" and not args.force: # https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9 @@ -190,15 +184,6 @@ def main(): print("Rerun `configure` with -enable-wallet, -with-utils and -with-daemon and rerun make") sys.exit(0) - # python3-zmq may not be installed. Handle this gracefully and with some helpful info - if enable_zmq: - try: - import zmq - except ImportError: - print("ERROR: \"import zmq\" failed. Use -nozmq to run without the ZMQ tests." - "To run zmq tests, see dependency info in /test/README.md.") - raise - # Build list of tests if tests: # Individual tests have been specified. Run specified tests that exist @@ -206,11 +191,9 @@ def main(): test_list = [t for t in ALL_SCRIPTS if (t in tests or re.sub(".py$", "", t) in tests)] else: - # No individual tests have been specified. Run base tests, and - # optionally ZMQ tests and extended tests. + # No individual tests have been specified. + # Run all base tests, and optionally run extended tests. test_list = BASE_SCRIPTS - if enable_zmq: - test_list += ZMQ_SCRIPTS if args.extended: # place the EXTENDED_SCRIPTS first since the three longest ones # are there and the list is shorter diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index 9e27b46381dc..fdcb0f0e89d7 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -3,11 +3,13 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the ZMQ API.""" +import configparser +import os +import struct +import sys from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import zmq -import struct class ZMQTest (BitcoinTestFramework): @@ -18,6 +20,21 @@ def __init__(self): port = 28332 def setup_nodes(self): + # Try to import python3-zmq. Skip this test if the import fails. + try: + import zmq + except ImportError: + self.log.warning("python3-zmq module not available. Skipping zmq tests!") + sys.exit(self.TEST_EXIT_SKIPPED) + + # Check that bitcoin has been built with ZMQ enabled + config = configparser.ConfigParser() + config.read_file(open(os.path.dirname(__file__) + "/config.ini")) + + if not config["components"].getboolean("ENABLE_ZMQ"): + self.log.warning("dashd has not been built with zmq enabled. Skipping zmq tests!") + sys.exit(self.TEST_EXIT_SKIPPED) + self.zmqContext = zmq.Context() self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") From 07b4c08bd76f80e5dd97d30bc70ced2d04457678 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 24 Apr 2017 14:43:38 +0200 Subject: [PATCH 147/987] Merge #9951: Wallet database handling abstractions/simplifications 911a480 wallet: Add comment describing the various classes in walletdb.h (Wladimir J. van der Laan) 69d2e9b wallet: Make IsDummy private in CWalletDBWrapper (Wladimir J. van der Laan) 3323281 wallet: CWalletDB CDB composition not inheritance (Wladimir J. van der Laan) be9e1a9 wallet: Reduce references to global bitdb environment (Wladimir J. van der Laan) 071c955 wallet: Get rid of fFileBacked (Wladimir J. van der Laan) 71afe3c wallet: Introduce database handle wrapper (Wladimir J. van der Laan) Tree-SHA512: e4e72953c61a2f6995d609a32f8ed8e18cab9a92bc9e193d46a1d1f06d9daa5c6da6fce2867d4e3ba4fc0439141901a3d35f246486f0fa8f59587786379dfcbd add 'batch.' Signed-off-by: Pasta remove `if (fFileBacked)` Signed-off-by: Pasta remove fFileBacked and strWalletFile Signed-off-by: Pasta --- src/qt/test/wallettests.cpp | 3 +- src/wallet/db.cpp | 126 +++++++++---- src/wallet/db.h | 59 +++++- src/wallet/rpcwallet.cpp | 2 +- src/wallet/test/wallet_test_fixture.cpp | 3 +- src/wallet/wallet.cpp | 231 ++++++++---------------- src/wallet/wallet.h | 38 ++-- src/wallet/walletdb.cpp | 121 ++++++++----- src/wallet/walletdb.h | 39 +++- 9 files changed, 364 insertions(+), 258 deletions(-) diff --git a/src/qt/test/wallettests.cpp b/src/qt/test/wallettests.cpp index 4656de90e20f..b3ee9a5d748e 100644 --- a/src/qt/test/wallettests.cpp +++ b/src/qt/test/wallettests.cpp @@ -86,7 +86,8 @@ void WalletTests::walletTests() TestChain100Setup test; test.CreateAndProcessBlock({}, GetScriptForRawPubKey(test.coinbaseKey.GetPubKey())); bitdb.MakeMock(); - CWallet wallet("wallet_test.dat"); + std::unique_ptr dbw(new CWalletDBWrapper(&bitdb, "wallet_test.dat")); + CWallet wallet(std::move(dbw)); bool firstRun; wallet.LoadWallet(firstRun); { diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index f0a5be2a66cc..98d6df3dc46d 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -358,13 +358,16 @@ void CDBEnv::CheckpointLSN(const std::string& strFile) } -CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL) +CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL) { int ret; fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); fFlushOnClose = fFlushOnCloseIn; - if (strFilename.empty()) + env = dbw.env; + if (dbw.IsDummy()) { return; + } + const std::string &strFilename = dbw.strFile; bool fCreate = strchr(pszMode, 'c') != NULL; unsigned int nFlags = DB_THREAD; @@ -372,17 +375,17 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose nFlags |= DB_CREATE; { - LOCK(bitdb.cs_db); - if (!bitdb.Open(GetDataDir())) + LOCK(env->cs_db); + if (!env->Open(GetDataDir())) throw std::runtime_error("CDB: Failed to open database environment."); strFile = strFilename; - ++bitdb.mapFileUseCount[strFile]; - pdb = bitdb.mapDb[strFile]; + ++env->mapFileUseCount[strFile]; + pdb = env->mapDb[strFile]; if (pdb == NULL) { - pdb = new Db(bitdb.dbenv, 0); + pdb = new Db(env->dbenv, 0); - bool fMockDb = bitdb.IsMock(); + bool fMockDb = env->IsMock(); if (fMockDb) { DbMpoolFile* mpf = pdb->get_mpf(); ret = mpf->set_flags(DB_MPOOL_NOFILE, 1); @@ -400,7 +403,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose if (ret != 0) { delete pdb; pdb = NULL; - --bitdb.mapFileUseCount[strFile]; + --env->mapFileUseCount[strFile]; strFile = ""; throw std::runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFilename)); } @@ -412,7 +415,7 @@ CDB::CDB(const std::string& strFilename, const char* pszMode, bool fFlushOnClose fReadOnly = fTmp; } - bitdb.mapDb[strFile] = pdb; + env->mapDb[strFile] = pdb; } } } @@ -427,7 +430,7 @@ void CDB::Flush() if (fReadOnly) nMinutes = 1; - bitdb.dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0); + env->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0); } void CDB::Close() @@ -443,8 +446,8 @@ void CDB::Close() Flush(); { - LOCK(bitdb.cs_db); - --bitdb.mapFileUseCount[strFile]; + LOCK(env->cs_db); + --env->mapFileUseCount[strFile]; } } @@ -471,23 +474,28 @@ bool CDBEnv::RemoveDb(const std::string& strFile) return (rc == 0); } -bool CDB::Rewrite(const std::string& strFile, const char* pszSkip) +bool CDB::Rewrite(CWalletDBWrapper& dbw, const char* pszSkip) { + if (dbw.IsDummy()) { + return true; + } + CDBEnv *env = dbw.env; + const std::string& strFile = dbw.strFile; while (true) { { - LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) { + LOCK(env->cs_db); + if (!env->mapFileUseCount.count(strFile) || env->mapFileUseCount[strFile] == 0) { // Flush log data to the dat file - bitdb.CloseDb(strFile); - bitdb.CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(strFile); + env->CloseDb(strFile); + env->CheckpointLSN(strFile); + env->mapFileUseCount.erase(strFile); bool fSuccess = true; LogPrintf("CDB::Rewrite: Rewriting %s...\n", strFile); std::string strFileRes = strFile + ".rewrite"; { // surround usage of db with extra {} - CDB db(strFile.c_str(), "r"); - Db* pdbCopy = new Db(bitdb.dbenv, 0); + CDB db(dbw, "r"); + Db* pdbCopy = new Db(env->dbenv, 0); int ret = pdbCopy->open(NULL, // Txn pointer strFileRes.c_str(), // Filename @@ -530,17 +538,17 @@ bool CDB::Rewrite(const std::string& strFile, const char* pszSkip) } if (fSuccess) { db.Close(); - bitdb.CloseDb(strFile); + env->CloseDb(strFile); if (pdbCopy->close(0)) fSuccess = false; delete pdbCopy; } } if (fSuccess) { - Db dbA(bitdb.dbenv, 0); + Db dbA(env->dbenv, 0); if (dbA.remove(strFile.c_str(), NULL, 0)) fSuccess = false; - Db dbB(bitdb.dbenv, 0); + Db dbB(env->dbenv, 0); if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0)) fSuccess = false; } @@ -595,16 +603,21 @@ void CDBEnv::Flush(bool fShutdown) } } -bool CDB::PeriodicFlush(std::string strFile) +bool CDB::PeriodicFlush(CWalletDBWrapper& dbw) { + if (dbw.IsDummy()) { + return true; + } bool ret = false; + CDBEnv *env = dbw.env; + const std::string& strFile = dbw.strFile; TRY_LOCK(bitdb.cs_db,lockDb); if (lockDb) { // Don't do this if any databases are in use int nRefCount = 0; - std::map::iterator mit = bitdb.mapFileUseCount.begin(); - while (mit != bitdb.mapFileUseCount.end()) + std::map::iterator mit = env->mapFileUseCount.begin(); + while (mit != env->mapFileUseCount.end()) { nRefCount += (*mit).second; mit++; @@ -613,17 +626,17 @@ bool CDB::PeriodicFlush(std::string strFile) if (nRefCount == 0) { boost::this_thread::interruption_point(); - std::map::iterator mi = bitdb.mapFileUseCount.find(strFile); - if (mi != bitdb.mapFileUseCount.end()) + std::map::iterator mi = env->mapFileUseCount.find(strFile); + if (mi != env->mapFileUseCount.end()) { LogPrint(BCLog::DB, "Flushing %s\n", strFile); int64_t nStart = GetTimeMillis(); // Flush wallet file so it's self contained - bitdb.CloseDb(strFile); - bitdb.CheckpointLSN(strFile); + env->CloseDb(strFile); + env->CheckpointLSN(strFile); - bitdb.mapFileUseCount.erase(mi++); + env->mapFileUseCount.erase(mi++); LogPrint(BCLog::DB, "Flushed %s %dms\n", strFile, GetTimeMillis() - nStart); ret = true; } @@ -632,3 +645,52 @@ bool CDB::PeriodicFlush(std::string strFile) return ret; } + +bool CWalletDBWrapper::Rewrite(const char* pszSkip) +{ + return CDB::Rewrite(*this, pszSkip); +} + +bool CWalletDBWrapper::Backup(const std::string& strDest) +{ + if (IsDummy()) { + return false; + } + while (true) + { + { + LOCK(env->cs_db); + if (!env->mapFileUseCount.count(strFile) || env->mapFileUseCount[strFile] == 0) + { + // Flush log data to the dat file + env->CloseDb(strFile); + env->CheckpointLSN(strFile); + env->mapFileUseCount.erase(strFile); + + // Copy wallet file + fs::path pathSrc = GetDataDir() / strFile; + fs::path pathDest(strDest); + if (fs::is_directory(pathDest)) + pathDest /= strFile; + + try { + fs::copy_file(pathSrc, pathDest, fs::copy_option::overwrite_if_exists); + LogPrintf("copied %s to %s\n", strFile, pathDest.string()); + return true; + } catch (const fs::filesystem_error& e) { + LogPrintf("error copying %s to %s - %s\n", strFile, pathDest.string(), e.what()); + return false; + } + } + } + MilliSleep(100); + } + return false; +} + +void CWalletDBWrapper::Flush(bool shutdown) +{ + if (!IsDummy()) { + env->Flush(shutdown); + } +} diff --git a/src/wallet/db.h b/src/wallet/db.h index d390574f49c7..c1fac5cada17 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -86,6 +86,52 @@ class CDBEnv extern CDBEnv bitdb; +/** An instance of this class represents one database. + * For BerkeleyDB this is just a (env, strFile) tuple. + **/ +class CWalletDBWrapper +{ + friend class CDB; +public: + /** Create dummy DB handle */ + CWalletDBWrapper(): env(nullptr) + { + } + + /** Create DB handle to real database */ + CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in): + env(env_in), strFile(strFile_in) + { + } + + /** Rewrite the entire database on disk, with the exception of key pszSkip if non-zero + */ + bool Rewrite(const char* pszSkip=nullptr); + + /** Back up the entire database to a file. + */ + bool Backup(const std::string& strDest); + + /** Get a name for this database, for debugging etc. + */ + std::string GetName() const { return strFile; } + + /** Make sure all changes are flushed to disk. + */ + void Flush(bool shutdown); + +private: + /** BerkeleyDB specific */ + CDBEnv *env; + std::string strFile; + + /** Return whether this database handle is a dummy for testing. + * Only to be used at a low level, application should ideally not care + * about this. + */ + bool IsDummy() { return env == nullptr; } +}; + /** RAII class that provides access to a Berkeley database */ class CDB @@ -96,18 +142,19 @@ class CDB DbTxn* activeTxn; bool fReadOnly; bool fFlushOnClose; + CDBEnv *env; - explicit CDB(const std::string& strFilename, const char* pszMode = "r+", bool fFlushOnCloseIn=true); +public: + explicit CDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool fFlushOnCloseIn=true); ~CDB() { Close(); } -public: void Flush(); void Close(); static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)); /* flush the wallet passively (TRY_LOCK) ideal to be called periodically */ - static bool PeriodicFlush(std::string strFile); + static bool PeriodicFlush(CWalletDBWrapper& dbw); /* verifies the database environment */ static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); /* verifies the database file */ @@ -117,7 +164,7 @@ class CDB CDB(const CDB&); void operator=(const CDB&); -protected: +public: template bool Read(const K& key, T& value) { @@ -157,7 +204,7 @@ class CDB bool Write(const K& key, const T& value, bool fOverwrite = true) { if (!pdb) - return false; + return true; if (fReadOnly) assert(!"Write called on database in read-only mode"); @@ -311,7 +358,7 @@ class CDB return Write(std::string("version"), nVersion); } - bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL); + bool static Rewrite(CWalletDBWrapper& dbw, const char* pszSkip = NULL); }; #endif // BITCOIN_WALLET_DB_H diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 49c1c119a359..9a63686e7dca 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2134,7 +2134,7 @@ UniValue walletpassphrase(const JSONRPCRequest& request) pwallet->TopUpKeyPool(); pwallet->nRelockTime = GetTime() + nSleepTime; - RPCRunLater(strprintf("lockwallet(%s)", pwallet->strWalletFile), boost::bind(LockWallet, pwallet), nSleepTime); + RPCRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), boost::bind(LockWallet, pwallet), nSleepTime); return NullUniValue; } diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index a76db376179d..1989bf8d9b96 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -14,7 +14,8 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName): bitdb.MakeMock(); bool fFirstRun; - pwalletMain = new CWallet("wallet_test.dat"); + std::unique_ptr dbw(new CWalletDBWrapper(&bitdb, "wallet_test.dat")); + pwalletMain = new CWallet(std::move(dbw)); pwalletMain->LoadWallet(fFirstRun); RegisterValidationInterface(pwalletMain); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 31819e66696b..c959309da835 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -286,10 +286,7 @@ bool CWallet::AddHDPubKey(const CExtPubKey &extPubKey, bool fInternal) if (HaveWatchOnly(script)) RemoveWatchOnly(script); - if (!fFileBacked) - return true; - - return CWalletDB(strWalletFile).WriteHDPubKey(hdPubKey, mapKeyMetadata[extPubKey.pubkey.GetID()]); + return CWalletDB(*dbw).WriteHDPubKey(hdPubKey, mapKeyMetadata[extPubKey.pubkey.GetID()]); } bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) @@ -307,10 +304,8 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey) if (HaveWatchOnly(script)) RemoveWatchOnly(script); - if (!fFileBacked) - return true; if (!IsCrypted()) { - return CWalletDB(strWalletFile).WriteKey(pubkey, + return CWalletDB(*dbw).WriteKey(pubkey, secret.GetPrivKey(), mapKeyMetadata[pubkey.GetID()]); } @@ -322,8 +317,6 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, { if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret)) return false; - if (!fFileBacked) - return true; { LOCK(cs_wallet); if (pwalletdbEncryption) @@ -331,7 +324,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); else - return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, + return CWalletDB(*dbw).WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); } @@ -367,9 +360,7 @@ bool CWallet::AddCScript(const CScript& redeemScript) { if (!CCryptoKeyStore::AddCScript(redeemScript)) return false; - if (!fFileBacked) - return true; - return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript); + return CWalletDB(*dbw).WriteCScript(Hash160(redeemScript), redeemScript); } bool CWallet::LoadCScript(const CScript& redeemScript) @@ -395,9 +386,7 @@ bool CWallet::AddWatchOnly(const CScript& dest) const CKeyMetadata& meta = mapKeyMetadata[CScriptID(dest)]; UpdateTimeFirstKey(meta.nCreateTime); NotifyWatchonlyChanged(true); - if (!fFileBacked) - return true; - return CWalletDB(strWalletFile).WriteWatchOnly(dest, meta); + return CWalletDB(*dbw).WriteWatchOnly(dest, meta); } bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime) @@ -413,9 +402,8 @@ bool CWallet::RemoveWatchOnly(const CScript &dest) return false; if (!HaveWatchOnly()) NotifyWatchonlyChanged(false); - if (fFileBacked) - if (!CWalletDB(strWalletFile).EraseWatchOnly(dest)) - return false; + if (!CWalletDB(*dbw).EraseWatchOnly(dest)) + return false; return true; } @@ -519,7 +507,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, return false; if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey)) return false; - CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second); + CWalletDB(*dbw).WriteMasterKey(pMasterKey.first, pMasterKey.second); if (fWasLocked) Lock(); @@ -544,7 +532,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, void CWallet::SetBestChain(const CBlockLocator& loc) { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); walletdb.WriteBestBlock(loc); } @@ -563,9 +551,8 @@ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, if (nVersion > nWalletMaxVersion) nWalletMaxVersion = nVersion; - if (fFileBacked) { - CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile); + CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(*dbw); if (nWalletVersion > 40000) pwalletdb->WriteMinVersion(nWalletVersion); if (!pwalletdbIn) @@ -612,7 +599,7 @@ std::set CWallet::GetConflicts(const uint256& txid) const void CWallet::Flush(bool shutdown) { - bitdb.Flush(shutdown); + dbw->Flush(shutdown); } bool CWallet::Verify() @@ -766,17 +753,14 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) { LOCK(cs_wallet); mapMasterKeys[++nMasterKeyMaxID] = kMasterKey; - if (fFileBacked) - { - assert(!pwalletdbEncryption); - pwalletdbEncryption = new CWalletDB(strWalletFile); - if (!pwalletdbEncryption->TxnBegin()) { - delete pwalletdbEncryption; - pwalletdbEncryption = NULL; - return false; - } - pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey); + assert(!pwalletdbEncryption); + pwalletdbEncryption = new CWalletDB(*dbw); + if (!pwalletdbEncryption->TxnBegin()) { + delete pwalletdbEncryption; + pwalletdbEncryption = NULL; + return false; } + pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey); // must get current HD chain before EncryptKeys CHDChain hdChainCurrent; @@ -784,10 +768,8 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) if (!EncryptKeys(_vMasterKey)) { - if (fFileBacked) { - pwalletdbEncryption->TxnAbort(); - delete pwalletdbEncryption; - } + pwalletdbEncryption->TxnAbort(); + delete pwalletdbEncryption; // We now probably have half of our keys encrypted in memory, and half not... // die and let the user reload the unencrypted wallet. assert(false); @@ -814,19 +796,16 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) // Encryption was introduced in version 0.4.0 SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true); - if (fFileBacked) - { - if (!pwalletdbEncryption->TxnCommit()) { - delete pwalletdbEncryption; - // We now have keys encrypted in memory, but not on disk... - // die to avoid confusion and let the user reload the unencrypted wallet. - assert(false); - } - + if (!pwalletdbEncryption->TxnCommit()) { delete pwalletdbEncryption; - pwalletdbEncryption = NULL; + // We now have keys encrypted in memory, but not on disk... + // die to avoid confusion and let the user reload the unencrypted wallet. + assert(false); } + delete pwalletdbEncryption; + pwalletdbEncryption = NULL; + Lock(); Unlock(strWalletPassphrase); @@ -842,7 +821,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) // Need to completely rewrite the wallet file; if we don't, bdb might keep // bits of the unencrypted private key in slack space in the database file. - CDB::Rewrite(strWalletFile); + dbw->Rewrite(); // Update KeePass if necessary if(GetBoolArg("-keepass", false)) { @@ -863,7 +842,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) DBErrors CWallet::ReorderTransactions() { LOCK(cs_wallet); - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); // Old wallets didn't have any defined order for transactions // Probably a bad idea to change the output of this @@ -944,14 +923,14 @@ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb) if (pwalletdb) { pwalletdb->WriteOrderPosNext(nOrderPosNext); } else { - CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext); + CWalletDB(*dbw).WriteOrderPosNext(nOrderPosNext); } return nRet; } bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment) { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); if (!walletdb.TxnBegin()) return false; @@ -985,7 +964,7 @@ bool CWallet::AccountMove(std::string strFrom, std::string strTo, CAmount nAmoun bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bForceNew) { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); CAccount account; walletdb.ReadAccount(strAccount, account); @@ -1037,7 +1016,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) { LOCK(cs_wallet); - CWalletDB walletdb(strWalletFile, "r+", fFlushOnClose); + CWalletDB walletdb(*dbw, "r+", fFlushOnClose); uint256 hash = wtxIn.GetHash(); @@ -1194,7 +1173,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) { LOCK2(cs_main, cs_wallet); - CWalletDB walletdb(strWalletFile, "r+"); + CWalletDB walletdb(*dbw, "r+"); std::set todo; std::set done; @@ -1269,7 +1248,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) return; // Do not flush the wallet here for performance reasons - CWalletDB walletdb(strWalletFile, "r+", false); + CWalletDB walletdb(*dbw, "r+", false); std::set todo; std::set done; @@ -1589,7 +1568,7 @@ bool CWallet::SetHDChain(const CHDChain& chain, bool memonly) if (!CCryptoKeyStore::SetHDChain(chain)) return false; - if (!memonly && !CWalletDB(strWalletFile).WriteHDChain(chain)) + if (!memonly && !CWalletDB(*dbw).WriteHDChain(chain)) throw std::runtime_error(std::string(__func__) + ": WriteHDChain failed"); return true; @@ -1603,13 +1582,11 @@ bool CWallet::SetCryptedHDChain(const CHDChain& chain, bool memonly) return false; if (!memonly) { - if (!fFileBacked) - return false; if (pwalletdbEncryption) { if (!pwalletdbEncryption->WriteCryptedHDChain(chain)) throw std::runtime_error(std::string(__func__) + ": WriteCryptedHDChain failed"); } else { - if (!CWalletDB(strWalletFile).WriteCryptedHDChain(chain)) + if (!CWalletDB(*dbw).WriteCryptedHDChain(chain)) throw std::runtime_error(std::string(__func__) + ": WriteCryptedHDChain failed"); } } @@ -3823,13 +3800,13 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon } void CWallet::ListAccountCreditDebit(const std::string& strAccount, std::list& entries) { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); return walletdb.ListAccountCreditDebit(strAccount, entries); } bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry) { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); return AddAccountingEntry(acentry, &walletdb); } @@ -3878,13 +3855,11 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { - if (!fFileBacked) - return DB_LOAD_OK; fFirstRunRet = false; - DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this); + DBErrors nLoadWalletRet = CWalletDB(*dbw,"cr+").LoadWallet(this); if (nLoadWalletRet == DB_NEED_REWRITE) { - if (CDB::Rewrite(strWalletFile, "\x04pool")) + if (dbw->Rewrite("\x04pool")) { LOCK(cs_wallet); setInternalKeyPool.clear(); @@ -3936,17 +3911,15 @@ void CWallet::AutoLockMasternodeCollaterals() DBErrors CWallet::ZapSelectTx(std::vector& vHashIn, std::vector& vHashOut) { - if (!fFileBacked) - return DB_LOAD_OK; AssertLockHeld(cs_wallet); // mapWallet vchDefaultKey = CPubKey(); - DBErrors nZapSelectTxRet = CWalletDB(strWalletFile,"cr+").ZapSelectTx(vHashIn, vHashOut); + DBErrors nZapSelectTxRet = CWalletDB(*dbw,"cr+").ZapSelectTx(vHashIn, vHashOut); for (uint256 hash : vHashOut) mapWallet.erase(hash); if (nZapSelectTxRet == DB_NEED_REWRITE) { - if (CDB::Rewrite(strWalletFile, "\x04pool")) + if (dbw->Rewrite("\x04pool")) { setInternalKeyPool.clear(); setExternalKeyPool.clear(); @@ -3967,13 +3940,11 @@ DBErrors CWallet::ZapSelectTx(std::vector& vHashIn, std::vector& vWtx) { - if (!fFileBacked) - return DB_LOAD_OK; vchDefaultKey = CPubKey(); - DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(vWtx); + DBErrors nZapWalletTxRet = CWalletDB(*dbw,"cr+").ZapWalletTx(vWtx); if (nZapWalletTxRet == DB_NEED_REWRITE) { - if (CDB::Rewrite(strWalletFile, "\x04pool")) + if (dbw->Rewrite("\x04pool")) { LOCK(cs_wallet); setInternalKeyPool.clear(); @@ -4005,11 +3976,9 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s } NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO, strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) ); - if (!fFileBacked) - return false; - if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose)) + if (!strPurpose.empty() && !CWalletDB(*dbw).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose)) return false; - return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName); + return CWalletDB(*dbw).WriteName(CBitcoinAddress(address).ToString(), strName); } bool CWallet::DelAddressBook(const CTxDestination& address) @@ -4017,33 +3986,25 @@ bool CWallet::DelAddressBook(const CTxDestination& address) { LOCK(cs_wallet); // mapAddressBook - if(fFileBacked) + // Delete destdata tuples associated with address + std::string strAddress = CBitcoinAddress(address).ToString(); + BOOST_FOREACH(const PAIRTYPE(std::string, std::string) &item, mapAddressBook[address].destdata) { - // Delete destdata tuples associated with address - std::string strAddress = CBitcoinAddress(address).ToString(); - BOOST_FOREACH(const PAIRTYPE(std::string, std::string) &item, mapAddressBook[address].destdata) - { - CWalletDB(strWalletFile).EraseDestData(strAddress, item.first); - } + CWalletDB(*dbw).EraseDestData(strAddress, item.first); } mapAddressBook.erase(address); } NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED); - if (!fFileBacked) - return false; - CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString()); - return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString()); + CWalletDB(*dbw).ErasePurpose(CBitcoinAddress(address).ToString()); + return CWalletDB(*dbw).EraseName(CBitcoinAddress(address).ToString()); } bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) { - if (fFileBacked) - { - if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey)) - return false; - } + if (!CWalletDB(*dbw).WriteDefaultKey(vchPubKey)) + return false; vchDefaultKey = vchPubKey; return true; } @@ -4056,7 +4017,7 @@ bool CWallet::NewKeyPool() { { LOCK(cs_wallet); - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); BOOST_FOREACH(int64_t nIndex, setInternalKeyPool) { walletdb.ErasePool(nIndex); } @@ -4118,7 +4079,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) nTargetSize *= 2; } bool fInternal = false; - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); for (int64_t i = missingInternal + missingExternal; i--;) { int64_t nEnd = 1; @@ -4167,7 +4128,7 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fIn if(setKeyPool.empty()) return; - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); nIndex = *setKeyPool.begin(); setKeyPool.erase(nIndex); @@ -4189,14 +4150,11 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fIn void CWallet::KeepKey(int64_t nIndex) { // Remove from key pool - if (fFileBacked) - { - CWalletDB walletdb(strWalletFile); - if (walletdb.ErasePool(nIndex)) - --nKeysLeftSinceAutoBackup; - if (!nWalletBackups) - nKeysLeftSinceAutoBackup = 0; - } + CWalletDB walletdb(*dbw); + if (walletdb.ErasePool(nIndex)) + --nKeysLeftSinceAutoBackup; + if (!nWalletBackups) + nKeysLeftSinceAutoBackup = 0; LogPrintf("keypool keep %d\n", nIndex); } @@ -4252,7 +4210,7 @@ int64_t CWallet::GetOldestKeyPoolTime() if (setExternalKeyPool.empty() && setInternalKeyPool.empty()) return GetTime(); - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); int64_t oldestKey = -1; // load oldest key from keypool, get time and return @@ -4400,7 +4358,7 @@ std::set< std::set > CWallet::GetAddressGroupings() CAmount CWallet::GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked) { - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); return GetAccountBalance(walletdb, strAccount, nMinDepth, filter, fAddLocked); } @@ -4497,7 +4455,7 @@ void CWallet::GetAllReserveKeys(std::set& setAddress) const { setAddress.clear(); - CWalletDB walletdb(strWalletFile); + CWalletDB walletdb(*dbw); LOCK2(cs_main, cs_wallet); LoadReserveKeysToSet(setAddress, setInternalKeyPool, walletdb); @@ -4755,18 +4713,14 @@ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, co return false; mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); - if (!fFileBacked) - return true; - return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value); + return CWalletDB(*dbw).WriteDestData(CBitcoinAddress(dest).ToString(), key, value); } bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key) { if (!mapAddressBook[dest].destdata.erase(key)) return false; - if (!fFileBacked) - return true; - return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key); + return CWalletDB(*dbw).EraseDestData(CBitcoinAddress(dest).ToString(), key); } bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) @@ -4845,7 +4799,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) if (GetBoolArg("-zapwallettxes", false)) { uiInterface.InitMessage(_("Zapping all transactions from wallet...")); - CWallet *tempWallet = new CWallet(walletFile); + std::unique_ptr dbw(new CWalletDBWrapper(&bitdb, walletFile)); + CWallet *tempWallet = new CWallet(std::move(dbw)); DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); if (nZapWalletRet != DB_LOAD_OK) { InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); @@ -4860,7 +4815,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) int64_t nStart = GetTimeMillis(); bool fFirstRun = true; - CWallet *walletInstance = new CWallet(walletFile); + std::unique_ptr dbw(new CWalletDBWrapper(&bitdb, walletFile)); + CWallet *walletInstance = new CWallet(std::move(dbw)); DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); if (nLoadWalletRet != DB_LOAD_OK) { @@ -4952,12 +4908,12 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) bool useHD = GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET); if (walletInstance->IsHDEnabled() && !useHD) { InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"), - walletInstance->strWalletFile)); + walletInstance->GetName())); return NULL; } if (!walletInstance->IsHDEnabled() && useHD) { InitError(strprintf(_("Error loading %s: You can't enable HD on a already existing non-HD wallet"), - walletInstance->strWalletFile)); + walletInstance->GetName())); return NULL; } } @@ -4974,7 +4930,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) CBlockIndex *pindexRescan = chainActive.Genesis(); if (!GetBoolArg("-rescan", false)) { - CWalletDB walletdb(walletFile); + CWalletDB walletdb(*walletInstance->dbw); CBlockLocator locator; if (walletdb.ReadBestBlock(locator)) pindexRescan = FindForkInGlobalIndex(chainActive, locator); @@ -5007,7 +4963,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) // Restore wallet transaction metadata after -zapwallettxes=1 if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") { - CWalletDB walletdb(walletFile); + CWalletDB walletdb(*walletInstance->dbw); BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) { @@ -5199,38 +5155,7 @@ bool CWallet::InitAutoBackup() bool CWallet::BackupWallet(const std::string& strDest) { - if (!fFileBacked) - return false; - while (true) - { - { - LOCK(bitdb.cs_db); - if (!bitdb.mapFileUseCount.count(strWalletFile) || bitdb.mapFileUseCount[strWalletFile] == 0) - { - // Flush log data to the dat file - bitdb.CloseDb(strWalletFile); - bitdb.CheckpointLSN(strWalletFile); - bitdb.mapFileUseCount.erase(strWalletFile); - - // Copy wallet file - fs::path pathSrc = GetDataDir() / strWalletFile; - fs::path pathDest(strDest); - if (fs::is_directory(pathDest)) - pathDest /= strWalletFile; - - try { - fs::copy_file(pathSrc, pathDest, fs::copy_option::overwrite_if_exists); - LogPrintf("copied %s to %s\n", strWalletFile, pathDest.string()); - return true; - } catch (const fs::filesystem_error& e) { - LogPrintf("error copying %s to %s - %s\n", strWalletFile, pathDest.string(), e.what()); - return false; - } - } - } - MilliSleep(100); - } - return false; + return dbw->Backup(strDest); } // This should be called carefully: @@ -5272,7 +5197,7 @@ bool AutoBackupWallet(CWallet* wallet, const std::string& strWalletFile_, std::s { // ... opened wallet LOCK2(cs_main, wallet->cs_wallet); - strWalletFile = wallet->strWalletFile; + strWalletFile = wallet->GetName(); fs::path backupFile = backupsDir / (strWalletFile + dateTimeStr); if(!wallet->BackupWallet(backupFile.string())) { strBackupWarningRet = strprintf(_("Failed to create backup %s!"), backupFile.string()); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 2371a54ecf7e..7d928a3a52a1 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -723,8 +723,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /* HD derive new child key (on internal or external chain) */ void DeriveNewChildKey(const CKeyMetadata& metadata, CKey& secretRet, uint32_t nAccountIndex, bool fInternal /*= false*/); - bool fFileBacked; - std::set setInternalKeyPool; std::set setExternalKeyPool; @@ -741,17 +739,33 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface */ bool AddWatchOnly(const CScript& dest) override; + std::unique_ptr dbw; + public: /* * Main wallet lock. - * This lock protects all the fields added by CWallet - * except for: - * fFileBacked (immutable after instantiation) - * strWalletFile (immutable after instantiation) + * This lock protects all the fields added by CWallet. */ mutable CCriticalSection cs_wallet; - const std::string strWalletFile; + /** Get database handle used by this wallet. Ideally this function would + * not be necessary. + */ + CWalletDBWrapper& GetDBHandle() + { + return *dbw; + } + + /** Get a name for this wallet for logging/debugging purposes. + */ + std::string GetName() const + { + if (dbw) { + return dbw->GetName(); + } else { + return "dummy"; + } + } void LoadKeyPool(int nIndex, const CKeyPool &keypool) { @@ -777,17 +791,16 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface MasterKeyMap mapMasterKeys; unsigned int nMasterKeyMaxID; - CWallet() + // Create wallet with dummy database handle + CWallet(): dbw(new CWalletDBWrapper()) { SetNull(); } - CWallet(const std::string& strWalletFileIn) - : strWalletFile(strWalletFileIn) + // Create wallet with passed-in database handle + CWallet(std::unique_ptr dbw_in) : dbw(std::move(dbw_in)) { SetNull(); - - fFileBacked = true; } ~CWallet() @@ -800,7 +813,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface { nWalletVersion = FEATURE_BASE; nWalletMaxVersion = FEATURE_BASE; - fFileBacked = false; nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; nOrderPosNext = 0; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 6c94ea566a26..b7ee76b2fd34 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -33,7 +33,7 @@ static std::atomic nWalletDBUpdateCounter; bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName) { nWalletDBUpdateCounter++; - return Write(make_pair(std::string("name"), strAddress), strName); + return batch.Write(std::make_pair(std::string("name"), strAddress), strName); } bool CWalletDB::EraseName(const std::string& strAddress) @@ -41,38 +41,38 @@ bool CWalletDB::EraseName(const std::string& strAddress) // This should only be used for sending addresses, never for receiving addresses, // receiving addresses must always have an address book entry if they're not change return. nWalletDBUpdateCounter++; - return Erase(make_pair(std::string("name"), strAddress)); + return batch.Erase(std::make_pair(std::string("name"), strAddress)); } bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose) { nWalletDBUpdateCounter++; - return Write(make_pair(std::string("purpose"), strAddress), strPurpose); + return batch.Write(std::make_pair(std::string("purpose"), strAddress), strPurpose); } bool CWalletDB::ErasePurpose(const std::string& strPurpose) { nWalletDBUpdateCounter++; - return Erase(make_pair(std::string("purpose"), strPurpose)); + return batch.Erase(std::make_pair(std::string("purpose"), strPurpose)); } bool CWalletDB::WriteTx(const CWalletTx& wtx) { nWalletDBUpdateCounter++; - return Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); + return batch.Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); } bool CWalletDB::EraseTx(uint256 hash) { nWalletDBUpdateCounter++; - return Erase(std::make_pair(std::string("tx"), hash)); + return batch.Erase(std::make_pair(std::string("tx"), hash)); } bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta) { nWalletDBUpdateCounter++; - if (!Write(std::make_pair(std::string("keymeta"), vchPubKey), + if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) return false; @@ -82,7 +82,7 @@ bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, c vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end()); - return Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); + return batch.Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); } bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, @@ -92,16 +92,16 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, const bool fEraseUnencryptedKey = true; nWalletDBUpdateCounter++; - if (!Write(std::make_pair(std::string("keymeta"), vchPubKey), + if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) return false; - if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) + if (!batch.Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) return false; if (fEraseUnencryptedKey) { - Erase(std::make_pair(std::string("key"), vchPubKey)); - Erase(std::make_pair(std::string("wkey"), vchPubKey)); + batch.Erase(std::make_pair(std::string("key"), vchPubKey)); + batch.Erase(std::make_pair(std::string("wkey"), vchPubKey)); } return true; } @@ -109,92 +109,92 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) { nWalletDBUpdateCounter++; - return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); + return batch.Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); } bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) { nWalletDBUpdateCounter++; - return Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); + return batch.Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); } bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta) { nWalletDBUpdateCounter++; - if (!Write(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) + if (!batch.Write(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) return false; - return Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); + return batch.Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); } bool CWalletDB::EraseWatchOnly(const CScript &dest) { nWalletDBUpdateCounter++; - if (!Erase(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) + if (!batch.Erase(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) return false; - return Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); + return batch.Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); } bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) { nWalletDBUpdateCounter++; - Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan - return Write(std::string("bestblock_nomerkle"), locator); + batch.Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan + return batch.Write(std::string("bestblock_nomerkle"), locator); } bool CWalletDB::ReadBestBlock(CBlockLocator& locator) { - if (Read(std::string("bestblock"), locator) && !locator.vHave.empty()) return true; - return Read(std::string("bestblock_nomerkle"), locator); + if (batch.Read(std::string("bestblock"), locator) && !locator.vHave.empty()) return true; + return batch.Read(std::string("bestblock_nomerkle"), locator); } bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext) { nWalletDBUpdateCounter++; - return Write(std::string("orderposnext"), nOrderPosNext); + return batch.Write(std::string("orderposnext"), nOrderPosNext); } bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey) { nWalletDBUpdateCounter++; - return Write(std::string("defaultkey"), vchPubKey); + return batch.Write(std::string("defaultkey"), vchPubKey); } bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool) { - return Read(std::make_pair(std::string("pool"), nPool), keypool); + return batch.Read(std::make_pair(std::string("pool"), nPool), keypool); } bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool) { nWalletDBUpdateCounter++; - return Write(std::make_pair(std::string("pool"), nPool), keypool); + return batch.Write(std::make_pair(std::string("pool"), nPool), keypool); } bool CWalletDB::ErasePool(int64_t nPool) { nWalletDBUpdateCounter++; - return Erase(std::make_pair(std::string("pool"), nPool)); + return batch.Erase(std::make_pair(std::string("pool"), nPool)); } bool CWalletDB::WriteMinVersion(int nVersion) { - return Write(std::string("minversion"), nVersion); + return batch.Write(std::string("minversion"), nVersion); } bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account) { account.SetNull(); - return Read(make_pair(std::string("acc"), strAccount), account); + return batch.Read(std::make_pair(std::string("acc"), strAccount), account); } bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account) { - return Write(make_pair(std::string("acc"), strAccount), account); + return batch.Write(std::make_pair(std::string("acc"), strAccount), account); } bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry) { - return Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); + return batch.Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); } bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry) @@ -218,7 +218,7 @@ void CWalletDB::ListAccountCreditDebit(const std::string& strAccount, std::list< { bool fAllAccounts = (strAccount == "*"); - Dbc* pcursor = GetCursor(); + Dbc* pcursor = batch.GetCursor(); if (!pcursor) throw std::runtime_error(std::string(__func__) + ": cannot create DB cursor"); bool setRange = true; @@ -229,7 +229,7 @@ void CWalletDB::ListAccountCreditDebit(const std::string& strAccount, std::list< if (setRange) ssKey << std::make_pair(std::string("acentry"), std::make_pair((fAllAccounts ? std::string("") : strAccount), uint64_t(0))); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = ReadAtCursor(pcursor, ssKey, ssValue, setRange); + int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue, setRange); setRange = false; if (ret == DB_NOTFOUND) break; @@ -589,7 +589,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) LOCK2(cs_main, pwallet->cs_wallet); try { int nMinVersion = 0; - if (Read((std::string)"minversion", nMinVersion)) + if (batch.Read((std::string)"minversion", nMinVersion)) { if (nMinVersion > CLIENT_VERSION) return DB_TOO_NEW; @@ -597,7 +597,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) } // Get cursor - Dbc* pcursor = GetCursor(); + Dbc* pcursor = batch.GetCursor(); if (!pcursor) { LogPrintf("Error getting wallet database cursor\n"); @@ -609,7 +609,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) // Read next record CDataStream ssKey(SER_DISK, CLIENT_VERSION); CDataStream ssValue(SER_DISK, CLIENT_VERSION); - int ret = ReadAtCursor(pcursor, ssKey, ssValue); + int ret = batch.ReadAtCursor(pcursor, ssKey, ssValue); if (ret == DB_NOTFOUND) break; else if (ret != 0) @@ -697,14 +697,14 @@ DBErrors CWalletDB::FindWalletTx(std::vector& vTxHash, std::vector CLIENT_VERSION) return DB_TOO_NEW; } // Get cursor - Dbc* pcursor = GetCursor(); + Dbc* pcursor = batch.GetCursor(); if (!pcursor) { LogPrintf("Error getting wallet database cursor\n"); @@ -716,7 +716,7 @@ DBErrors CWalletDB::FindWalletTx(std::vector& vTxHash, std::vector= 2) { - const std::string& strFile = pwalletMain->strWalletFile; - if (CDB::PeriodicFlush(strFile)) + if (CDB::PeriodicFlush(pwalletMain->GetDBHandle())) { nLastFlushed = CWalletDB::GetUpdateCounter(); + } } fOneThread = false; } @@ -888,29 +888,29 @@ bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) { nWalletDBUpdateCounter++; - return Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); + return batch.Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); } bool CWalletDB::EraseDestData(const std::string &address, const std::string &key) { nWalletDBUpdateCounter++; - return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key))); + return batch.Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key))); } bool CWalletDB::WriteHDChain(const CHDChain& chain) { nWalletDBUpdateCounter++; - return Write(std::string("hdchain"), chain); + return batch.Write(std::string("hdchain"), chain); } bool CWalletDB::WriteCryptedHDChain(const CHDChain& chain) { nWalletDBUpdateCounter++; - if (!Write(std::string("chdchain"), chain)) + if (!batch.Write(std::string("chdchain"), chain)) return false; - Erase(std::string("hdchain")); + batch.Erase(std::string("hdchain")); return true; } @@ -919,10 +919,10 @@ bool CWalletDB::WriteHDPubKey(const CHDPubKey& hdPubKey, const CKeyMetadata& key { nWalletDBUpdateCounter++; - if (!Write(std::make_pair(std::string("keymeta"), hdPubKey.extPubKey.pubkey), keyMeta, false)) + if (!batch.Write(std::make_pair(std::string("keymeta"), hdPubKey.extPubKey.pubkey), keyMeta, false)) return false; - return Write(std::make_pair(std::string("hdpubkey"), hdPubKey.extPubKey.pubkey), hdPubKey, false); + return batch.Write(std::make_pair(std::string("hdpubkey"), hdPubKey.extPubKey.pubkey), hdPubKey, false); } void CWalletDB::IncrementUpdateCounter() @@ -934,3 +934,28 @@ unsigned int CWalletDB::GetUpdateCounter() { return nWalletDBUpdateCounter; } + +bool CWalletDB::TxnBegin() +{ + return batch.TxnBegin(); +} + +bool CWalletDB::TxnCommit() +{ + return batch.TxnCommit(); +} + +bool CWalletDB::TxnAbort() +{ + return batch.TxnAbort(); +} + +bool CWalletDB::ReadVersion(int& nVersion) +{ + return batch.ReadVersion(nVersion); +} + +bool CWalletDB::WriteVersion(int nVersion) +{ + return batch.WriteVersion(nVersion); +} diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index c333c36a0d1e..fd9da46be559 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -17,6 +17,21 @@ #include #include +/** + * Overview of wallet database classes: + * + * - CDBEnv is an environment in which the database exists (has no analog in dbwrapper.h) + * - CWalletDBWrapper represents a wallet database (similar to CDBWrapper in dbwrapper.h) + * - CDB is a low-level database transaction (similar to CDBBatch in dbwrapper.h) + * - CWalletDB is a modifier object for the wallet, and encapsulates a database + * transaction as well as methods to act on the database (no analog in + * dbwrapper.h) + * + * The latter two are named confusingly, in contrast to what the names CDB + * and CWalletDB suggest they are transient transaction objects and don't + * represent the database itself. + */ + static const bool DEFAULT_FLUSHWALLET = true; class CAccount; @@ -73,11 +88,16 @@ class CKeyMetadata } }; -/** Access to the wallet database */ -class CWalletDB : public CDB +/** Access to the wallet database. + * This should really be named CWalletDBBatch, as it represents a single transaction at the + * database. It will be committed when the object goes out of scope. + * Optionally (on by default) it will flush to disk as well. + */ +class CWalletDB { public: - CWalletDB(const std::string& strFilename, const char* pszMode = "r+", bool _fFlushOnClose = true) : CDB(strFilename, pszMode, _fFlushOnClose) + CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) : + batch(dbw, pszMode, _fFlushOnClose) { } @@ -151,7 +171,20 @@ class CWalletDB : public CDB static void IncrementUpdateCounter(); static unsigned int GetUpdateCounter(); + + //! Begin a new transaction + bool TxnBegin(); + //! Commit current transaction + bool TxnCommit(); + //! Abort current transaction + bool TxnAbort(); + //! Read wallet version + bool ReadVersion(int& nVersion); + //! Write wallet version + bool WriteVersion(int nVersion); private: + CDB batch; + CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); }; From 56d1d13c439fc75e6c4157d49549a0e6333510a2 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Tue, 11 Jun 2019 06:42:17 -0500 Subject: [PATCH 148/987] Backport 8824 (#2968) * Merge #8824: Refactor TxToJSON() and ScriptPubKeyToJSON() 0ff9320 refactor TxToJSON() and ScriptPubKeyToJSON() (jonnynewbs) Tree-SHA512: caf7d590829e221522edd5b1ab8ce67b53a2c6986d3bbe8477eab420b1007bf60f885ed0a25ba9587e468c00768360ddc31db37847e862858573eaed5ed8b0d6 * remove witness and vsize Signed-off-by: Pasta * Add valueSat To preserve rpc output format * Move extrapayload and special tx json output to `TxToUniv` * Add spent index info --- src/core_io.h | 4 +- src/core_write.cpp | 94 ++++++++++++++- src/evo/cbtx.cpp | 12 -- src/evo/cbtx.h | 15 ++- src/evo/providertx.cpp | 63 ---------- src/evo/providertx.h | 70 ++++++++++- src/llmq/quorums_commitment.cpp | 24 ---- src/llmq/quorums_commitment.h | 26 +++- src/rest.cpp | 9 +- src/rpc/blockchain.cpp | 5 +- src/rpc/rawtransaction.cpp | 137 +++------------------- src/spentindex.h | 5 + test/util/data/blanktxv1.json | 1 + test/util/data/blanktxv2.json | 1 + test/util/data/tt-delin1-out.json | 3 + test/util/data/tt-delout1-out.json | 2 + test/util/data/tt-locktime317000-out.json | 3 + test/util/data/txcreate1.json | 3 + test/util/data/txcreate2.json | 2 + test/util/data/txcreatedata1.json | 3 + test/util/data/txcreatedata2.json | 3 + test/util/data/txcreatedata_seq0.json | 2 + test/util/data/txcreatedata_seq1.json | 2 + test/util/data/txcreatemultisig1.json | 2 + test/util/data/txcreatemultisig2.json | 2 + test/util/data/txcreateoutpubkey1.json | 2 + test/util/data/txcreatescript1.json | 2 + test/util/data/txcreatescript2.json | 2 + test/util/data/txcreatesignv1.json | 2 + 29 files changed, 260 insertions(+), 241 deletions(-) diff --git a/src/core_io.h b/src/core_io.h index d889197aa661..f7f9c4958e7a 100644 --- a/src/core_io.h +++ b/src/core_io.h @@ -15,6 +15,8 @@ struct CMutableTransaction; class uint256; class UniValue; +struct CSpentIndexTxInfo; + // core_read.cpp CScript ParseScript(const std::string& s); std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false); @@ -28,6 +30,6 @@ std::vector ParseHexUV(const UniValue& v, const std::string& strN std::string FormatScript(const CScript& script); std::string EncodeHexTx(const CTransaction& tx); void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); -void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry); +void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, const CSpentIndexTxInfo* ptxSpentInfo = nullptr); #endif // BITCOIN_CORE_IO_H diff --git a/src/core_write.cpp b/src/core_write.cpp index 787298162c24..113c57ff34ee 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -10,11 +10,18 @@ #include "script/standard.h" #include "serialize.h" #include "streams.h" -#include +#include "univalue.h" #include "util.h" #include "utilmoneystr.h" #include "utilstrencodings.h" +#include "spentindex.h" + +#include "evo/cbtx.h" +#include "evo/providertx.h" +#include "evo/specialtx.h" +#include "llmq/quorums_commitment.h" + #include #include @@ -146,10 +153,12 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey, out.pushKV("addresses", a); } -void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry) +void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, const CSpentIndexTxInfo* ptxSpentInfo) { - entry.pushKV("txid", tx.GetHash().GetHex()); + uint256 txid = tx.GetHash(); + entry.pushKV("txid", txid.GetHex()); entry.pushKV("version", tx.nVersion); + entry.pushKV("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION)); entry.pushKV("locktime", (int64_t)tx.nLockTime); UniValue vin(UniValue::VARR); @@ -164,6 +173,23 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry) o.pushKV("asm", ScriptToAsmStr(txin.scriptSig, true)); o.pushKV("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())); in.pushKV("scriptSig", o); + + // Add address and value info if spentindex enabled + if (ptxSpentInfo != nullptr) { + CSpentIndexKey spentKey(txin.prevout.hash, txin.prevout.n); + auto it = ptxSpentInfo->mSpentInfo.find(spentKey); + if (it != ptxSpentInfo->mSpentInfo.end()) { + auto spentInfo = it->second; + UniValue outValue(UniValue::VNUM, FormatMoney(spentInfo.satoshis)); + in.push_back(Pair("value", outValue)); + in.push_back(Pair("valueSat", spentInfo.satoshis)); + if (spentInfo.addressType == 1) { + in.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); + } else if (spentInfo.addressType == 2) { + in.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); + } + } + } } in.pushKV("sequence", (int64_t)txin.nSequence); vin.push_back(in); @@ -178,15 +204,77 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry) UniValue outValue(UniValue::VNUM, FormatMoney(txout.nValue)); out.pushKV("value", outValue); + out.pushKV("valueSat", txout.nValue); out.pushKV("n", (int64_t)i); UniValue o(UniValue::VOBJ); ScriptPubKeyToUniv(txout.scriptPubKey, o, true); out.pushKV("scriptPubKey", o); + + // Add spent information if spentindex is enabled + if (ptxSpentInfo != nullptr) { + CSpentIndexKey spentKey(txid, i); + auto it = ptxSpentInfo->mSpentInfo.find(spentKey); + if (it != ptxSpentInfo->mSpentInfo.end()) { + auto spentInfo = it->second; + out.push_back(Pair("spentTxId", spentInfo.txid.GetHex())); + out.push_back(Pair("spentIndex", (int)spentInfo.inputIndex)); + out.push_back(Pair("spentHeight", spentInfo.blockHeight)); + } + } vout.push_back(out); } entry.pushKV("vout", vout); + if (!tx.vExtraPayload.empty()) { + entry.push_back(Pair("extraPayloadSize", (int)tx.vExtraPayload.size())); + entry.push_back(Pair("extraPayload", HexStr(tx.vExtraPayload))); + } + + if (tx.nType == TRANSACTION_PROVIDER_REGISTER) { + CProRegTx proTx; + if (GetTxPayload(tx, proTx)) { + UniValue obj; + proTx.ToJson(obj); + entry.push_back(Pair("proRegTx", obj)); + } + } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { + CProUpServTx proTx; + if (GetTxPayload(tx, proTx)) { + UniValue obj; + proTx.ToJson(obj); + entry.push_back(Pair("proUpServTx", obj)); + } + } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { + CProUpRegTx proTx; + if (GetTxPayload(tx, proTx)) { + UniValue obj; + proTx.ToJson(obj); + entry.push_back(Pair("proUpRegTx", obj)); + } + } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) { + CProUpRevTx proTx; + if (GetTxPayload(tx, proTx)) { + UniValue obj; + proTx.ToJson(obj); + entry.push_back(Pair("proUpRevTx", obj)); + } + } else if (tx.nType == TRANSACTION_COINBASE) { + CCbTx cbTx; + if (GetTxPayload(tx, cbTx)) { + UniValue obj; + cbTx.ToJson(obj); + entry.push_back(Pair("cbTx", obj)); + } + } else if (tx.nType == TRANSACTION_QUORUM_COMMITMENT) { + llmq::CFinalCommitmentTxPayload qcTx; + if (GetTxPayload(tx, qcTx)) { + UniValue obj; + qcTx.ToJson(obj); + entry.push_back(Pair("qcTx", obj)); + } + } + if (!hashBlock.IsNull()) entry.pushKV("blockhash", hashBlock.GetHex()); diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 12646b2a4d29..cc7412ed2746 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -236,15 +236,3 @@ std::string CCbTx::ToString() const return strprintf("CCbTx(nHeight=%d, nVersion=%d, merkleRootMNList=%s, merkleRootQuorums=%s)", nVersion, nHeight, merkleRootMNList.ToString(), merkleRootQuorums.ToString()); } - -void CCbTx::ToJson(UniValue& obj) const -{ - obj.clear(); - obj.setObject(); - obj.push_back(Pair("version", (int)nVersion)); - obj.push_back(Pair("height", (int)nHeight)); - obj.push_back(Pair("merkleRootMNList", merkleRootMNList.ToString())); - if (nVersion >= 2) { - obj.push_back(Pair("merkleRootQuorums", merkleRootQuorums.ToString())); - } -} diff --git a/src/evo/cbtx.h b/src/evo/cbtx.h index 0df252d1e088..a746a1f9e409 100644 --- a/src/evo/cbtx.h +++ b/src/evo/cbtx.h @@ -7,10 +7,10 @@ #include "consensus/validation.h" #include "primitives/transaction.h" +#include "univalue.h" class CBlock; class CBlockIndex; -class UniValue; // coinbase transaction class CCbTx @@ -40,7 +40,18 @@ class CCbTx } std::string ToString() const; - void ToJson(UniValue& obj) const; + + void ToJson(UniValue& obj) const + { + obj.clear(); + obj.setObject(); + obj.push_back(Pair("version", (int)nVersion)); + obj.push_back(Pair("height", (int)nHeight)); + obj.push_back(Pair("merkleRootMNList", merkleRootMNList.ToString())); + if (nVersion >= 2) { + obj.push_back(Pair("merkleRootQuorums", merkleRootQuorums.ToString())); + } + } }; bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state); diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp index 47259ce3edbe..5db4dda4cdbb 100644 --- a/src/evo/providertx.cpp +++ b/src/evo/providertx.cpp @@ -421,28 +421,6 @@ std::string CProRegTx::ToString() const nVersion, collateralOutpoint.ToStringShort(), addr.ToString(), (double)nOperatorReward / 100, CBitcoinAddress(keyIDOwner).ToString(), pubKeyOperator.ToString(), CBitcoinAddress(keyIDVoting).ToString(), payee); } -void CProRegTx::ToJson(UniValue& obj) const -{ - obj.clear(); - obj.setObject(); - obj.push_back(Pair("version", nVersion)); - obj.push_back(Pair("collateralHash", collateralOutpoint.hash.ToString())); - obj.push_back(Pair("collateralIndex", (int)collateralOutpoint.n)); - obj.push_back(Pair("service", addr.ToString(false))); - obj.push_back(Pair("ownerAddress", CBitcoinAddress(keyIDOwner).ToString())); - obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString())); - - CTxDestination dest; - if (ExtractDestination(scriptPayout, dest)) { - CBitcoinAddress bitcoinAddress(dest); - obj.push_back(Pair("payoutAddress", bitcoinAddress.ToString())); - } - obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); - obj.push_back(Pair("operatorReward", (double)nOperatorReward / 100)); - - obj.push_back(Pair("inputsHash", inputsHash.ToString())); -} - std::string CProUpServTx::ToString() const { CTxDestination dest; @@ -455,21 +433,6 @@ std::string CProUpServTx::ToString() const nVersion, proTxHash.ToString(), addr.ToString(), payee); } -void CProUpServTx::ToJson(UniValue& obj) const -{ - obj.clear(); - obj.setObject(); - obj.push_back(Pair("version", nVersion)); - obj.push_back(Pair("proTxHash", proTxHash.ToString())); - obj.push_back(Pair("service", addr.ToString(false))); - CTxDestination dest; - if (ExtractDestination(scriptOperatorPayout, dest)) { - CBitcoinAddress bitcoinAddress(dest); - obj.push_back(Pair("operatorPayoutAddress", bitcoinAddress.ToString())); - } - obj.push_back(Pair("inputsHash", inputsHash.ToString())); -} - std::string CProUpRegTx::ToString() const { CTxDestination dest; @@ -482,34 +445,8 @@ std::string CProUpRegTx::ToString() const nVersion, proTxHash.ToString(), pubKeyOperator.ToString(), CBitcoinAddress(keyIDVoting).ToString(), payee); } -void CProUpRegTx::ToJson(UniValue& obj) const -{ - obj.clear(); - obj.setObject(); - obj.push_back(Pair("version", nVersion)); - obj.push_back(Pair("proTxHash", proTxHash.ToString())); - obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString())); - CTxDestination dest; - if (ExtractDestination(scriptPayout, dest)) { - CBitcoinAddress bitcoinAddress(dest); - obj.push_back(Pair("payoutAddress", bitcoinAddress.ToString())); - } - obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); - obj.push_back(Pair("inputsHash", inputsHash.ToString())); -} - std::string CProUpRevTx::ToString() const { return strprintf("CProUpRevTx(nVersion=%d, proTxHash=%s, nReason=%d)", nVersion, proTxHash.ToString(), nReason); } - -void CProUpRevTx::ToJson(UniValue& obj) const -{ - obj.clear(); - obj.setObject(); - obj.push_back(Pair("version", nVersion)); - obj.push_back(Pair("proTxHash", proTxHash.ToString())); - obj.push_back(Pair("reason", (int)nReason)); - obj.push_back(Pair("inputsHash", inputsHash.ToString())); -} diff --git a/src/evo/providertx.h b/src/evo/providertx.h index bb5c0f18ebc0..d7526ed60195 100644 --- a/src/evo/providertx.h +++ b/src/evo/providertx.h @@ -9,11 +9,12 @@ #include "consensus/validation.h" #include "primitives/transaction.h" +#include "base58.h" #include "netaddress.h" #include "pubkey.h" +#include "univalue.h" class CBlockIndex; -class UniValue; class CProRegTx { @@ -61,7 +62,28 @@ class CProRegTx std::string MakeSignString() const; std::string ToString() const; - void ToJson(UniValue& obj) const; + + void ToJson(UniValue& obj) const + { + obj.clear(); + obj.setObject(); + obj.push_back(Pair("version", nVersion)); + obj.push_back(Pair("collateralHash", collateralOutpoint.hash.ToString())); + obj.push_back(Pair("collateralIndex", (int)collateralOutpoint.n)); + obj.push_back(Pair("service", addr.ToString(false))); + obj.push_back(Pair("ownerAddress", CBitcoinAddress(keyIDOwner).ToString())); + obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString())); + + CTxDestination dest; + if (ExtractDestination(scriptPayout, dest)) { + CBitcoinAddress bitcoinAddress(dest); + obj.push_back(Pair("payoutAddress", bitcoinAddress.ToString())); + } + obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); + obj.push_back(Pair("operatorReward", (double)nOperatorReward / 100)); + + obj.push_back(Pair("inputsHash", inputsHash.ToString())); + } }; class CProUpServTx @@ -95,7 +117,21 @@ class CProUpServTx public: std::string ToString() const; - void ToJson(UniValue& obj) const; + + void ToJson(UniValue& obj) const + { + obj.clear(); + obj.setObject(); + obj.push_back(Pair("version", nVersion)); + obj.push_back(Pair("proTxHash", proTxHash.ToString())); + obj.push_back(Pair("service", addr.ToString(false))); + CTxDestination dest; + if (ExtractDestination(scriptOperatorPayout, dest)) { + CBitcoinAddress bitcoinAddress(dest); + obj.push_back(Pair("operatorPayoutAddress", bitcoinAddress.ToString())); + } + obj.push_back(Pair("inputsHash", inputsHash.ToString())); + } }; class CProUpRegTx @@ -133,7 +169,22 @@ class CProUpRegTx public: std::string ToString() const; - void ToJson(UniValue& obj) const; + + void ToJson(UniValue& obj) const + { + obj.clear(); + obj.setObject(); + obj.push_back(Pair("version", nVersion)); + obj.push_back(Pair("proTxHash", proTxHash.ToString())); + obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString())); + CTxDestination dest; + if (ExtractDestination(scriptPayout, dest)) { + CBitcoinAddress bitcoinAddress(dest); + obj.push_back(Pair("payoutAddress", bitcoinAddress.ToString())); + } + obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); + obj.push_back(Pair("inputsHash", inputsHash.ToString())); + } }; class CProUpRevTx @@ -174,7 +225,16 @@ class CProUpRevTx public: std::string ToString() const; - void ToJson(UniValue& obj) const; + + void ToJson(UniValue& obj) const + { + obj.clear(); + obj.setObject(); + obj.push_back(Pair("version", nVersion)); + obj.push_back(Pair("proTxHash", proTxHash.ToString())); + obj.push_back(Pair("reason", (int)nReason)); + obj.push_back(Pair("inputsHash", inputsHash.ToString())); + } }; diff --git a/src/llmq/quorums_commitment.cpp b/src/llmq/quorums_commitment.cpp index ea26b24ea733..ff707a091a01 100644 --- a/src/llmq/quorums_commitment.cpp +++ b/src/llmq/quorums_commitment.cpp @@ -10,8 +10,6 @@ #include "evo/specialtx.h" -#include - namespace llmq { @@ -133,28 +131,6 @@ bool CFinalCommitment::VerifySizes(const Consensus::LLMQParams& params) const return true; } -void CFinalCommitment::ToJson(UniValue& obj) const -{ - obj.setObject(); - obj.push_back(Pair("version", (int)nVersion)); - obj.push_back(Pair("llmqType", (int)llmqType)); - obj.push_back(Pair("quorumHash", quorumHash.ToString())); - obj.push_back(Pair("signersCount", CountSigners())); - obj.push_back(Pair("validMembersCount", CountValidMembers())); - obj.push_back(Pair("quorumPublicKey", quorumPublicKey.ToString())); -} - -void CFinalCommitmentTxPayload::ToJson(UniValue& obj) const -{ - obj.setObject(); - obj.push_back(Pair("version", (int)nVersion)); - obj.push_back(Pair("height", (int)nHeight)); - - UniValue qcObj; - commitment.ToJson(qcObj); - obj.push_back(Pair("commitment", qcObj)); -} - bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state) { CFinalCommitmentTxPayload qcTx; diff --git a/src/llmq/quorums_commitment.h b/src/llmq/quorums_commitment.h index f2c27372b7a5..480395b872a4 100644 --- a/src/llmq/quorums_commitment.h +++ b/src/llmq/quorums_commitment.h @@ -11,6 +11,8 @@ #include "bls/bls.h" +#include "univalue.h" + namespace llmq { @@ -52,8 +54,6 @@ class CFinalCommitment bool VerifyNull() const; bool VerifySizes(const Consensus::LLMQParams& params) const; - void ToJson(UniValue& obj) const; - public: ADD_SERIALIZE_METHODS @@ -86,6 +86,17 @@ class CFinalCommitment } return true; } + + void ToJson(UniValue& obj) const + { + obj.setObject(); + obj.push_back(Pair("version", (int)nVersion)); + obj.push_back(Pair("llmqType", (int)llmqType)); + obj.push_back(Pair("quorumHash", quorumHash.ToString())); + obj.push_back(Pair("signersCount", CountSigners())); + obj.push_back(Pair("validMembersCount", CountValidMembers())); + obj.push_back(Pair("quorumPublicKey", quorumPublicKey.ToString())); + } }; class CFinalCommitmentTxPayload @@ -109,7 +120,16 @@ class CFinalCommitmentTxPayload READWRITE(commitment); } - void ToJson(UniValue& obj) const; + void ToJson(UniValue& obj) const + { + obj.setObject(); + obj.push_back(Pair("version", (int)nVersion)); + obj.push_back(Pair("height", (int)nHeight)); + + UniValue qcObj; + commitment.ToJson(qcObj); + obj.push_back(Pair("commitment", qcObj)); + } }; bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state); diff --git a/src/rest.cpp b/src/rest.cpp index 57c17257917e..7bca7488e95c 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -5,6 +5,7 @@ #include "chain.h" #include "chainparams.h" +#include "core_io.h" #include "primitives/block.h" #include "primitives/transaction.h" #include "validation.h" @@ -59,10 +60,6 @@ struct CCoin { } }; -/* Defined in rawtransaction.cpp */ -void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry); -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex); - static bool RESTERR(HTTPRequest* req, enum HTTPStatusCode status, std::string message) { req->WriteHeader("Content-Type", "text/plain"); @@ -386,7 +383,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart) case RF_JSON: { UniValue objTx(UniValue::VOBJ); - TxToJSON(*tx, hashBlock, objTx); + TxToUniv(*tx, hashBlock, objTx); std::string strJSON = objTx.write() + "\n"; req->WriteHeader("Content-Type", "application/json"); req->WriteReply(HTTP_OK, strJSON); @@ -568,7 +565,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) // include the script in a json output UniValue o(UniValue::VOBJ); - ScriptPubKeyToJSON(coin.out.scriptPubKey, o, true); + ScriptPubKeyToUniv(coin.out.scriptPubKey, o, true); utxo.push_back(Pair("scriptPubKey", o)); utxos.push_back(utxo); } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 68ac4d76ed2f..1ded789e017b 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -15,6 +15,7 @@ #include "consensus/validation.h" #include "instantsend.h" #include "validation.h" +#include "core_io.h" #include "policy/policy.h" #include "primitives/transaction.h" #include "rpc/server.h" @@ -134,7 +135,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx if(txDetails) { UniValue objTx(UniValue::VOBJ); - TxToJSON(*tx, uint256(), objTx); + TxToUniv(*tx, uint256(), objTx); txs.push_back(objTx); } else @@ -1235,7 +1236,7 @@ UniValue gettxout(const JSONRPCRequest& request) } ret.push_back(Pair("value", ValueFromAmount(coin.out.nValue))); UniValue o(UniValue::VOBJ); - ScriptPubKeyToJSON(coin.out.scriptPubKey, o, true); + ScriptPubKeyToUniv(coin.out.scriptPubKey, o, true); ret.push_back(Pair("scriptPubKey", o)); ret.push_back(Pair("coinbase", (bool)coin.fCoinBase)); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index a44af1d84a0d..9bdf5fdd2f6e 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -44,141 +44,37 @@ #include -void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex) -{ - txnouttype type; - std::vector addresses; - int nRequired; - - out.push_back(Pair("asm", ScriptToAsmStr(scriptPubKey))); - if (fIncludeHex) - out.push_back(Pair("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); - - if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) { - out.push_back(Pair("type", GetTxnOutputType(type))); - return; - } - - out.push_back(Pair("reqSigs", nRequired)); - out.push_back(Pair("type", GetTxnOutputType(type))); - - UniValue a(UniValue::VARR); - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); - out.push_back(Pair("addresses", a)); -} void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) { + // Call into TxToUniv() in bitcoin-common to decode the transaction hex. + // + // Blockchain contextual information (confirmations and blocktime) is not + // available to code in bitcoin-common, so we query them here and push the + // data into the returned UniValue. + uint256 txid = tx.GetHash(); - entry.push_back(Pair("txid", txid.GetHex())); - entry.push_back(Pair("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION))); - entry.push_back(Pair("version", tx.nVersion)); - entry.push_back(Pair("type", tx.nType)); - entry.push_back(Pair("locktime", (int64_t)tx.nLockTime)); - UniValue vin(UniValue::VARR); - BOOST_FOREACH(const CTxIn& txin, tx.vin) { - UniValue in(UniValue::VOBJ); - if (tx.IsCoinBase()) - in.push_back(Pair("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); - else { - in.push_back(Pair("txid", txin.prevout.hash.GetHex())); - in.push_back(Pair("vout", (int64_t)txin.prevout.n)); - UniValue o(UniValue::VOBJ); - o.push_back(Pair("asm", ScriptToAsmStr(txin.scriptSig, true))); - o.push_back(Pair("hex", HexStr(txin.scriptSig.begin(), txin.scriptSig.end()))); - in.push_back(Pair("scriptSig", o)); - - // Add address and value info if spentindex enabled + + // Add spent information if spentindex is enabled + CSpentIndexTxInfo txSpentInfo; + for (const auto& txin : tx.vin) { + if (!tx.IsCoinBase()) { CSpentIndexValue spentInfo; CSpentIndexKey spentKey(txin.prevout.hash, txin.prevout.n); if (GetSpentIndex(spentKey, spentInfo)) { - in.push_back(Pair("value", ValueFromAmount(spentInfo.satoshis))); - in.push_back(Pair("valueSat", spentInfo.satoshis)); - if (spentInfo.addressType == 1) { - in.push_back(Pair("address", CBitcoinAddress(CKeyID(spentInfo.addressHash)).ToString())); - } else if (spentInfo.addressType == 2) { - in.push_back(Pair("address", CBitcoinAddress(CScriptID(spentInfo.addressHash)).ToString())); - } + txSpentInfo.mSpentInfo.emplace(spentKey, spentInfo); } - } - in.push_back(Pair("sequence", (int64_t)txin.nSequence)); - vin.push_back(in); } - entry.push_back(Pair("vin", vin)); - UniValue vout(UniValue::VARR); for (unsigned int i = 0; i < tx.vout.size(); i++) { - const CTxOut& txout = tx.vout[i]; - UniValue out(UniValue::VOBJ); - out.push_back(Pair("value", ValueFromAmount(txout.nValue))); - out.push_back(Pair("valueSat", txout.nValue)); - out.push_back(Pair("n", (int64_t)i)); - UniValue o(UniValue::VOBJ); - ScriptPubKeyToJSON(txout.scriptPubKey, o, true); - out.push_back(Pair("scriptPubKey", o)); - - // Add spent information if spentindex is enabled CSpentIndexValue spentInfo; CSpentIndexKey spentKey(txid, i); if (GetSpentIndex(spentKey, spentInfo)) { - out.push_back(Pair("spentTxId", spentInfo.txid.GetHex())); - out.push_back(Pair("spentIndex", (int)spentInfo.inputIndex)); - out.push_back(Pair("spentHeight", spentInfo.blockHeight)); + txSpentInfo.mSpentInfo.emplace(spentKey, spentInfo); } - - vout.push_back(out); } - entry.push_back(Pair("vout", vout)); - if (!tx.vExtraPayload.empty()) { - entry.push_back(Pair("extraPayloadSize", (int)tx.vExtraPayload.size())); - entry.push_back(Pair("extraPayload", HexStr(tx.vExtraPayload))); - } - - if (tx.nType == TRANSACTION_PROVIDER_REGISTER) { - CProRegTx proTx; - if (GetTxPayload(tx, proTx)) { - UniValue obj; - proTx.ToJson(obj); - entry.push_back(Pair("proRegTx", obj)); - } - } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { - CProUpServTx proTx; - if (GetTxPayload(tx, proTx)) { - UniValue obj; - proTx.ToJson(obj); - entry.push_back(Pair("proUpServTx", obj)); - } - } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) { - CProUpRegTx proTx; - if (GetTxPayload(tx, proTx)) { - UniValue obj; - proTx.ToJson(obj); - entry.push_back(Pair("proUpRegTx", obj)); - } - } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) { - CProUpRevTx proTx; - if (GetTxPayload(tx, proTx)) { - UniValue obj; - proTx.ToJson(obj); - entry.push_back(Pair("proUpRevTx", obj)); - } - } else if (tx.nType == TRANSACTION_COINBASE) { - CCbTx cbTx; - if (GetTxPayload(tx, cbTx)) { - UniValue obj; - cbTx.ToJson(obj); - entry.push_back(Pair("cbTx", obj)); - } - } else if (tx.nType == TRANSACTION_QUORUM_COMMITMENT) { - llmq::CFinalCommitmentTxPayload qcTx; - if (GetTxPayload(tx, qcTx)) { - UniValue obj; - qcTx.ToJson(obj); - entry.push_back(Pair("qcTx", obj)); - } - } + TxToUniv(tx, uint256(), entry, &txSpentInfo); bool chainLock = false; if (!hashBlock.IsNull()) { @@ -199,6 +95,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) } } } + bool fLocked = instantsend.IsLockedInstantSendTransaction(txid); bool fLLMQLocked = llmq::quorumInstantSendManager->IsLocked(txid); entry.push_back(Pair("instantlock", fLocked || fLLMQLocked || chainLock)); @@ -621,7 +518,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed"); UniValue result(UniValue::VOBJ); - TxToJSON(CTransaction(std::move(mtx)), uint256(), result); + TxToUniv(CTransaction(std::move(mtx)), uint256(), result); return result; } @@ -661,7 +558,7 @@ UniValue decodescript(const JSONRPCRequest& request) } else { // Empty scripts are valid } - ScriptPubKeyToJSON(script, r, false); + ScriptPubKeyToUniv(script, r, false); UniValue type; diff --git a/src/spentindex.h b/src/spentindex.h index a3d84e86d0c3..dec3a00070d3 100644 --- a/src/spentindex.h +++ b/src/spentindex.h @@ -96,6 +96,11 @@ struct CSpentIndexKeyCompare } }; +struct CSpentIndexTxInfo +{ + std::map mSpentInfo; +}; + struct CTimestampIndexIteratorKey { unsigned int timestamp; diff --git a/test/util/data/blanktxv1.json b/test/util/data/blanktxv1.json index f6d6ab58842c..9f52d23f8787 100644 --- a/test/util/data/blanktxv1.json +++ b/test/util/data/blanktxv1.json @@ -1,6 +1,7 @@ { "txid": "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43", "version": 1, + "size": 10, "locktime": 0, "vin": [ ], diff --git a/test/util/data/blanktxv2.json b/test/util/data/blanktxv2.json index 59165bb512f5..8ef4489c5376 100644 --- a/test/util/data/blanktxv2.json +++ b/test/util/data/blanktxv2.json @@ -1,6 +1,7 @@ { "txid": "4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a", "version": 2, + "size": 10, "locktime": 0, "vin": [ ], diff --git a/test/util/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json index cb2dbd2120d7..db9bf301bb09 100644 --- a/test/util/data/tt-delin1-out.json +++ b/test/util/data/tt-delin1-out.json @@ -1,6 +1,7 @@ { "txid": "81b2035be1da1abe745c6141174a73d151009ec17b3d5ebffa2e177408c50dfd", "version": 1, + "size": 3040, "locktime": 0, "vin": [ { @@ -187,6 +188,7 @@ "vout": [ { "value": 1.3782, + "valueSat": 137820000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", @@ -200,6 +202,7 @@ }, { "value": 0.01000001, + "valueSat": 1000001, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json index ca2de5fc6338..6d0036e1a5bc 100644 --- a/test/util/data/tt-delout1-out.json +++ b/test/util/data/tt-delout1-out.json @@ -1,6 +1,7 @@ { "txid": "c46ccd75b5050e942b2e86a3648f843f525fe6fc000bf0534ba5973063354493", "version": 1, + "size": 3155, "locktime": 0, "vin": [ { @@ -196,6 +197,7 @@ "vout": [ { "value": 1.3782, + "valueSat": 137820000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json index 70c9cf3b77fe..9cb44ac98978 100644 --- a/test/util/data/tt-locktime317000-out.json +++ b/test/util/data/tt-locktime317000-out.json @@ -1,6 +1,7 @@ { "txid": "aded538f642c17e15f4d3306b8be7e1a4d1ae0c4616d641ab51ea09ba65e5cb5", "version": 1, + "size": 3189, "locktime": 317000, "vin": [ { @@ -196,6 +197,7 @@ "vout": [ { "value": 1.3782, + "valueSat": 137820000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 8fd139bb39ced713f231c58a4d07bf6954d1c201 OP_EQUALVERIFY OP_CHECKSIG", @@ -209,6 +211,7 @@ }, { "value": 0.01000001, + "valueSat": 1000001, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 6c772e9cf96371bba3da8cb733da70a2fcf20078 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/txcreate1.json b/test/util/data/txcreate1.json index e646ff994202..1eece2ef8c40 100644 --- a/test/util/data/txcreate1.json +++ b/test/util/data/txcreate1.json @@ -1,6 +1,7 @@ { "txid": "fe7d174f42dce0cffa7a527e9bc8368956057619ec817648f6138b98f2533e8f", "version": 2, + "size": 201, "locktime": 0, "vin": [ { @@ -34,6 +35,7 @@ "vout": [ { "value": 0.18, + "valueSat": 18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", @@ -47,6 +49,7 @@ }, { "value": 4.00, + "valueSat": 400000000, "n": 1, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 f2d4db28cad6502226ee484ae24505c2885cb12d OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/txcreate2.json b/test/util/data/txcreate2.json index bce5c9b090f0..ea4e12b57f4b 100644 --- a/test/util/data/txcreate2.json +++ b/test/util/data/txcreate2.json @@ -1,12 +1,14 @@ { "txid": "0481afb29931341d0d7861d8a2f6f26456fa042abf54a23e96440ed7946e0715", "version": 2, + "size": 19, "locktime": 0, "vin": [ ], "vout": [ { "value": 0.00, + "valueSat": 0, "n": 0, "scriptPubKey": { "asm": "", diff --git a/test/util/data/txcreatedata1.json b/test/util/data/txcreatedata1.json index e6108f6e291f..7c37f8b18b15 100644 --- a/test/util/data/txcreatedata1.json +++ b/test/util/data/txcreatedata1.json @@ -1,6 +1,7 @@ { "txid": "07894b4d12fe7853dd911402db1620920d261b9627c447f931417d330c25f06e", "version": 1, + "size": 176, "locktime": 0, "vin": [ { @@ -16,6 +17,7 @@ "vout": [ { "value": 0.18, + "valueSat": 18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", @@ -29,6 +31,7 @@ }, { "value": 4.00, + "valueSat": 400000000, "n": 1, "scriptPubKey": { "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", diff --git a/test/util/data/txcreatedata2.json b/test/util/data/txcreatedata2.json index 62ca31aa3497..eba7e7d4c282 100644 --- a/test/util/data/txcreatedata2.json +++ b/test/util/data/txcreatedata2.json @@ -1,6 +1,7 @@ { "txid": "c14b007fa3a6c1e7765919c1d14c1cfc2b8642c3a5d3be4b1fa8c4ccfec98bb0", "version": 2, + "size": 176, "locktime": 0, "vin": [ { @@ -16,6 +17,7 @@ "vout": [ { "value": 0.18, + "valueSat": 18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", @@ -29,6 +31,7 @@ }, { "value": 0.00, + "valueSat": 0, "n": 1, "scriptPubKey": { "asm": "OP_RETURN 54686973204f505f52455455524e207472616e73616374696f6e206f7574707574207761732063726561746564206279206d6f646966696564206372656174657261777472616e73616374696f6e2e", diff --git a/test/util/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json index 463169873cd0..e13a1d101139 100644 --- a/test/util/data/txcreatedata_seq0.json +++ b/test/util/data/txcreatedata_seq0.json @@ -1,6 +1,7 @@ { "txid": "8df6ed527472542dd5e137c242a7c5a9f337ac34f7b257ae4af886aeaebb51b0", "version": 2, + "size": 85, "locktime": 0, "vin": [ { @@ -16,6 +17,7 @@ "vout": [ { "value": 0.18, + "valueSat": 18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json index 41cc4b42db58..a76c952327de 100644 --- a/test/util/data/txcreatedata_seq1.json +++ b/test/util/data/txcreatedata_seq1.json @@ -1,6 +1,7 @@ { "txid": "c4dea671b0d7b48f8ab10bc46650e8329d3c5766931f548f513847a19f5ba75b", "version": 1, + "size": 126, "locktime": 0, "vin": [ { @@ -25,6 +26,7 @@ "vout": [ { "value": 0.18, + "valueSat": 18000000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 1fc11f39be1729bf973a7ab6a615ca4729d64574 OP_EQUALVERIFY OP_CHECKSIG", diff --git a/test/util/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json index d7f9101dd041..a707abed0c68 100644 --- a/test/util/data/txcreatemultisig1.json +++ b/test/util/data/txcreatemultisig1.json @@ -1,12 +1,14 @@ { "txid": "0d1d4edfc217d9db3ab6a9298f26a52eae3c52f55a6cb8ccbc14f7c727572894", "version": 1, + "size": 124, "locktime": 0, "vin": [ ], "vout": [ { "value": 1.00, + "valueSat": 100000000, "n": 0, "scriptPubKey": { "asm": "2 02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 021ac43c7ff740014c3b33737ede99c967e4764553d1b2b83db77c83b8715fa72d 02df2089105c77f266fa11a9d33f05c735234075f2e8780824c6b709415f9fb485 3 OP_CHECKMULTISIG", diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json index e7e95312d94e..79d477f620c4 100644 --- a/test/util/data/txcreatemultisig2.json +++ b/test/util/data/txcreatemultisig2.json @@ -1,12 +1,14 @@ { "txid": "0d861f278a3b7bce7cb5a88d71e6e6a903336f95ad5a2c29b295b63835b6eee3", "version": 1, + "size": 42, "locktime": 0, "vin": [ ], "vout": [ { "value": 1.00, + "valueSat": 100000000, "n": 0, "scriptPubKey": { "asm": "OP_HASH160 1c6fbaf46d64221e80cbae182c33ddf81b9294ac OP_EQUAL", diff --git a/test/util/data/txcreateoutpubkey1.json b/test/util/data/txcreateoutpubkey1.json index 74a3ac4c8bb3..e9f48ee99b2a 100644 --- a/test/util/data/txcreateoutpubkey1.json +++ b/test/util/data/txcreateoutpubkey1.json @@ -1,12 +1,14 @@ { "txid": "f42b38ac12e3fafc96ba1a9ba70cbfe326744aef75df5fb9db5d6e2855ca415f", "version": 1, + "size": 54, "locktime": 0, "vin": [ ], "vout": [ { "value": 0.00, + "valueSat": 0, "n": 0, "scriptPubKey": { "asm": "02a5613bd857b7048924264d1e70e08fb2a7e6527d32b7ab1bb993ac59964ff397 OP_CHECKSIG", diff --git a/test/util/data/txcreatescript1.json b/test/util/data/txcreatescript1.json index e54564fbada7..0eadaf32d3a6 100644 --- a/test/util/data/txcreatescript1.json +++ b/test/util/data/txcreatescript1.json @@ -1,12 +1,14 @@ { "txid": "f0851b68202f736b792649cfc960259c2374badcb644ab20cac726b5f72f61c9", "version": 1, + "size": 20, "locktime": 0, "vin": [ ], "vout": [ { "value": 0.00, + "valueSat": 0, "n": 0, "scriptPubKey": { "asm": "OP_DROP", diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json index 95b1f368d8e2..25ad9caad768 100644 --- a/test/util/data/txcreatescript2.json +++ b/test/util/data/txcreatescript2.json @@ -1,12 +1,14 @@ { "txid": "6e07a7cc075e0703f32ee8c4e5373fe654bfbc315148fda364e1be286ff290d0", "version": 1, + "size": 42, "locktime": 0, "vin": [ ], "vout": [ { "value": 0.00, + "valueSat": 0, "n": 0, "scriptPubKey": { "asm": "OP_HASH160 71ed53322d470bb96657deb786b94f97dd46fb15 OP_EQUAL", diff --git a/test/util/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json index 5956e704d283..b6a3d5894ed0 100644 --- a/test/util/data/txcreatesignv1.json +++ b/test/util/data/txcreatesignv1.json @@ -1,6 +1,7 @@ { "txid": "977e7cd286cb72cd470d539ba6cb48400f8f387d97451d45cdb8819437a303af", "version": 1, + "size": 224, "locktime": 0, "vin": [ { @@ -16,6 +17,7 @@ "vout": [ { "value": 0.001, + "valueSat": 100000, "n": 0, "scriptPubKey": { "asm": "OP_DUP OP_HASH160 5834479edbbe0539b31ffd3a8f8ebadc2165ed01 OP_EQUALVERIFY OP_CHECKSIG", From d931cb723e69f2f57daadb5f599cda5e5d8f57d1 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Tue, 11 Jun 2019 06:46:07 -0500 Subject: [PATCH 149/987] Update copyright date (2019) (#2970) Signed-off-by: Pasta --- src/batchedlogger.cpp | 2 +- src/bench/bls.cpp | 2 +- src/bls/bls.cpp | 2 +- src/bls/bls.h | 2 +- src/bls/bls_worker.cpp | 2 +- src/bls/bls_worker.h | 2 +- src/cachemap.h | 2 +- src/cachemultimap.h | 2 +- src/dash-cli.cpp | 2 +- src/evo/cbtx.cpp | 2 +- src/evo/cbtx.h | 2 +- src/evo/deterministicmns.h | 2 +- src/evo/evodb.cpp | 2 +- src/evo/evodb.h | 2 +- src/evo/simplifiedmns.h | 2 +- src/evo/specialtx.cpp | 2 +- src/evo/specialtx.h | 2 +- src/flat-database.h | 2 +- src/governance/governance-classes.cpp | 2 +- src/governance/governance-classes.h | 2 +- src/governance/governance-exceptions.h | 2 +- src/governance/governance-validators.cpp | 2 +- src/governance/governance-validators.h | 2 +- src/governance/governance-vote.h | 2 +- src/governance/governance-votedb.cpp | 2 +- src/governance/governance-votedb.h | 2 +- src/hash.h | 2 +- src/hdchain.cpp | 2 +- src/hdchain.h | 2 +- src/keepass.cpp | 2 +- src/keepass.h | 2 +- src/llmq/quorums_blockprocessor.h | 2 +- src/llmq/quorums_commitment.cpp | 2 +- src/llmq/quorums_commitment.h | 2 +- src/llmq/quorums_dkgsessionmgr.h | 2 +- src/messagesigner.cpp | 2 +- src/messagesigner.h | 2 +- src/miner.cpp | 2 +- src/netfulfilledman.cpp | 2 +- src/netfulfilledman.h | 2 +- src/privatesend/privatesend-util.cpp | 2 +- src/privatesend/privatesend-util.h | 2 +- src/qt/addressbookpage.cpp | 2 +- src/qt/askpassphrasedialog.cpp | 2 +- src/qt/bitcoinaddressvalidator.cpp | 2 +- src/qt/bitcoinunits.cpp | 2 +- src/qt/bitcoinunits.h | 2 +- src/qt/clientmodel.h | 2 +- src/qt/coincontroldialog.cpp | 2 +- src/qt/editaddressdialog.cpp | 2 +- src/qt/guiconstants.h | 2 +- src/qt/networkstyle.h | 2 +- src/qt/openuridialog.cpp | 2 +- src/qt/overviewpage.cpp | 2 +- src/qt/rpcconsole.cpp | 2 +- src/qt/sendcoinsdialog.cpp | 2 +- src/qt/sendcoinsentry.cpp | 2 +- src/qt/splashscreen.cpp | 2 +- src/qt/transactiondesc.cpp | 2 +- src/qt/transactionrecord.cpp | 2 +- src/qt/walletmodel.cpp | 2 +- src/rpc/net.cpp | 2 +- src/rpc/rawtransaction.cpp | 2 +- src/rpc/server.cpp | 2 +- src/stacktraces.cpp | 2 +- src/stacktraces.h | 2 +- src/test/bip39_tests.cpp | 2 +- src/test/cachemap_tests.cpp | 2 +- src/test/cachemultimap_tests.cpp | 2 +- src/test/evo_deterministicmns_tests.cpp | 2 +- src/test/governance_validators_tests.cpp | 2 +- src/test/ratecheck_tests.cpp | 2 +- src/test/test_dash.h | 2 +- src/uint256.h | 2 +- src/validation.h | 2 +- src/version.h | 2 +- src/wallet/rpcdump.cpp | 2 +- src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.h | 2 +- src/wallet/walletdb.cpp | 2 +- 80 files changed, 80 insertions(+), 80 deletions(-) diff --git a/src/batchedlogger.cpp b/src/batchedlogger.cpp index e2a75bb31742..89d5a4e6691c 100644 --- a/src/batchedlogger.cpp +++ b/src/batchedlogger.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 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. diff --git a/src/bench/bls.cpp b/src/bench/bls.cpp index 827af86d8100..cd7332cc0434 100644 --- a/src/bench/bls.cpp +++ b/src/bench/bls.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/bls/bls.cpp b/src/bls/bls.cpp index bcf3d7ad1bf2..f6d06ae7fecc 100644 --- a/src/bls/bls.cpp +++ b/src/bls/bls.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/bls/bls.h b/src/bls/bls.h index e099982940cd..5f1c58c44e78 100644 --- a/src/bls/bls.h +++ b/src/bls/bls.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/bls/bls_worker.cpp b/src/bls/bls_worker.cpp index c87d5c89a3e8..6375eb47e234 100644 --- a/src/bls/bls_worker.cpp +++ b/src/bls/bls_worker.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 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. diff --git a/src/bls/bls_worker.h b/src/bls/bls_worker.h index 691163dbb71c..e1190910372a 100644 --- a/src/bls/bls_worker.h +++ b/src/bls/bls_worker.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 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. diff --git a/src/cachemap.h b/src/cachemap.h index 03a30c20ff91..8b45b670142a 100644 --- a/src/cachemap.h +++ b/src/cachemap.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/cachemultimap.h b/src/cachemultimap.h index 25e2ea7ffc7e..306dcc5c305c 100644 --- a/src/cachemultimap.h +++ b/src/cachemultimap.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/dash-cli.cpp b/src/dash-cli.cpp index 5c9070034d91..26c6da8be679 100644 --- a/src/dash-cli.cpp +++ b/src/dash-cli.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2017 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index cc7412ed2746..1778e171cc0c 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018 The Dash Core developers +// Copyright (c) 2017-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/cbtx.h b/src/evo/cbtx.h index a746a1f9e409..80cca5b767aa 100644 --- a/src/evo/cbtx.h +++ b/src/evo/cbtx.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018 The Dash Core developers +// Copyright (c) 2017-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 4e6e2dd5879e..1e9e9725d26e 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/evodb.cpp b/src/evo/evodb.cpp index 138353dbae7a..b46d6efcb177 100644 --- a/src/evo/evodb.cpp +++ b/src/evo/evodb.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/evodb.h b/src/evo/evodb.h index ead20ce6fee0..dbc8d64ba689 100644 --- a/src/evo/evodb.h +++ b/src/evo/evodb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/simplifiedmns.h b/src/evo/simplifiedmns.h index b9637936bcf2..bf67043f7fc2 100644 --- a/src/evo/simplifiedmns.h +++ b/src/evo/simplifiedmns.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018 The Dash Core developers +// Copyright (c) 2017-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/specialtx.cpp b/src/evo/specialtx.cpp index dd141f968715..e641cd0fd113 100644 --- a/src/evo/specialtx.cpp +++ b/src/evo/specialtx.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/evo/specialtx.h b/src/evo/specialtx.h index 75f7b10cffeb..fd5756652a6c 100644 --- a/src/evo/specialtx.h +++ b/src/evo/specialtx.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/flat-database.h b/src/flat-database.h index d97ef517be74..0f4ec0ad19f5 100644 --- a/src/flat-database.h +++ b/src/flat-database.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2017 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/governance/governance-classes.cpp b/src/governance/governance-classes.cpp index 0cce9518680d..29c6b0c4f229 100644 --- a/src/governance/governance-classes.cpp +++ b/src/governance/governance-classes.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/governance/governance-classes.h b/src/governance/governance-classes.h index 3ed4f3f0062f..24cbee6dbf6b 100644 --- a/src/governance/governance-classes.h +++ b/src/governance/governance-classes.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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 GOVERNANCE_CLASSES_H diff --git a/src/governance/governance-exceptions.h b/src/governance/governance-exceptions.h index 100c4e4942dd..68265b7bab98 100644 --- a/src/governance/governance-exceptions.h +++ b/src/governance/governance-exceptions.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/governance/governance-validators.cpp b/src/governance/governance-validators.cpp index eccc8def66b1..64907024b537 100644 --- a/src/governance/governance-validators.cpp +++ b/src/governance/governance-validators.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/governance/governance-validators.h b/src/governance/governance-validators.h index 3d78a69f0c81..d17766345a68 100644 --- a/src/governance/governance-validators.h +++ b/src/governance/governance-validators.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/governance/governance-vote.h b/src/governance/governance-vote.h index 6879e2ba0191..13502986e1f5 100644 --- a/src/governance/governance-vote.h +++ b/src/governance/governance-vote.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/governance/governance-votedb.cpp b/src/governance/governance-votedb.cpp index ad08530c4b48..5f70d7c7a4aa 100644 --- a/src/governance/governance-votedb.cpp +++ b/src/governance/governance-votedb.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/governance/governance-votedb.h b/src/governance/governance-votedb.h index e3e61a25953c..2a18e6f0add4 100644 --- a/src/governance/governance-votedb.h +++ b/src/governance/governance-votedb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/hash.h b/src/hash.h index dc467e7d14d0..e4e579f3c44d 100644 --- a/src/hash.h +++ b/src/hash.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/hdchain.cpp b/src/hdchain.cpp index a397f8ba5bc0..da6398dab6de 100644 --- a/src/hdchain.cpp +++ b/src/hdchain.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying #include "base58.h" diff --git a/src/hdchain.h b/src/hdchain.h index c278de0c5ec9..d381dbfd610e 100644 --- a/src/hdchain.h +++ b/src/hdchain.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying #ifndef DASH_HDCHAIN_H #define DASH_HDCHAIN_H diff --git a/src/keepass.cpp b/src/keepass.cpp index 97d96dfa0650..3a5d25c8cba8 100644 --- a/src/keepass.cpp +++ b/src/keepass.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/keepass.h b/src/keepass.h index 2849db2ff89b..769bbd18a688 100644 --- a/src/keepass.h +++ b/src/keepass.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/llmq/quorums_blockprocessor.h b/src/llmq/quorums_blockprocessor.h index c3e1bcf56eb1..937494ea9639 100644 --- a/src/llmq/quorums_blockprocessor.h +++ b/src/llmq/quorums_blockprocessor.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 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. diff --git a/src/llmq/quorums_commitment.cpp b/src/llmq/quorums_commitment.cpp index ff707a091a01..1d7d38fd31d0 100644 --- a/src/llmq/quorums_commitment.cpp +++ b/src/llmq/quorums_commitment.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 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. diff --git a/src/llmq/quorums_commitment.h b/src/llmq/quorums_commitment.h index 480395b872a4..15a2a28b0ad1 100644 --- a/src/llmq/quorums_commitment.h +++ b/src/llmq/quorums_commitment.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 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. diff --git a/src/llmq/quorums_dkgsessionmgr.h b/src/llmq/quorums_dkgsessionmgr.h index cfb9850ec0e6..d943f25a2600 100644 --- a/src/llmq/quorums_dkgsessionmgr.h +++ b/src/llmq/quorums_dkgsessionmgr.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 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. diff --git a/src/messagesigner.cpp b/src/messagesigner.cpp index 676d7ead9df8..80894dba3051 100644 --- a/src/messagesigner.cpp +++ b/src/messagesigner.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/messagesigner.h b/src/messagesigner.h index 9c0873c3e616..870a854c854e 100644 --- a/src/messagesigner.h +++ b/src/messagesigner.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/miner.cpp b/src/miner.cpp index 93591da4e2bb..676ed7c8fd10 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/netfulfilledman.cpp b/src/netfulfilledman.cpp index bff379e0f160..aed9d2811021 100644 --- a/src/netfulfilledman.cpp +++ b/src/netfulfilledman.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/netfulfilledman.h b/src/netfulfilledman.h index b9c992c3646a..8fd9799498d8 100644 --- a/src/netfulfilledman.h +++ b/src/netfulfilledman.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/privatesend/privatesend-util.cpp b/src/privatesend/privatesend-util.cpp index 99571e0d866b..9ac8c12d080a 100644 --- a/src/privatesend/privatesend-util.cpp +++ b/src/privatesend/privatesend-util.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/privatesend/privatesend-util.h b/src/privatesend/privatesend-util.h index 348ce8502386..1d41e5feb9b4 100644 --- a/src/privatesend/privatesend-util.h +++ b/src/privatesend/privatesend-util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index b60b0a916d4e..a30c06ecae0e 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2017 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp index 2367c38f79d3..c68a7801cd4f 100644 --- a/src/qt/askpassphrasedialog.cpp +++ b/src/qt/askpassphrasedialog.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoinaddressvalidator.cpp b/src/qt/bitcoinaddressvalidator.cpp index e026046d7a99..e95a4276cbf8 100644 --- a/src/qt/bitcoinaddressvalidator.cpp +++ b/src/qt/bitcoinaddressvalidator.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers -// Copyright (c) 2014-2016 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp index eabff0644890..b2f6bd471197 100644 --- a/src/qt/bitcoinunits.cpp +++ b/src/qt/bitcoinunits.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2016 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/bitcoinunits.h b/src/qt/bitcoinunits.h index a1ef0fda4977..42171881d6b0 100644 --- a/src/qt/bitcoinunits.h +++ b/src/qt/bitcoinunits.h @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2016 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 846a71d46a85..67ad63b41e6a 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2017 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 01a31f056b0d..b9d3a9bd78c6 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp index 7f712b0a549d..a4f12070b580 100644 --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers -// Copyright (c) 2014-2016 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 9d47c56691e8..d70fc5b61778 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/networkstyle.h b/src/qt/networkstyle.h index e547aca0fd95..af6bafa77450 100644 --- a/src/qt/networkstyle.h +++ b/src/qt/networkstyle.h @@ -1,5 +1,5 @@ // Copyright (c) 2014 The Bitcoin Core developers -// Copyright (c) 2014-2016 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/openuridialog.cpp b/src/qt/openuridialog.cpp index 0f30089c98cc..43b7da99ff98 100644 --- a/src/qt/openuridialog.cpp +++ b/src/qt/openuridialog.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2014 The Bitcoin Core developers -// Copyright (c) 2014-2016 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index f4bcbac87f3a..6d2ef3bbbd20 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 9bf1ea96df7a..f2ffd9edd712 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index d9757c704dc9..0649e6d8fa85 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index ae9e9482743f..85030fe4e97c 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2016 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index b5dba251755f..580540a3a576 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 16525b104b9b..00ed287ce99f 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2017 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index aee7720f8196..fb78a17f9c26 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 080b9a92dce3..31875dc6fda6 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2011-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 458771fd4aaf..8dc2748ce6c3 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 9bdf5fdd2f6e..b993c3818526 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 1df9304bc015..3e1f8c1824fe 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/stacktraces.cpp b/src/stacktraces.cpp index 94307ab65649..a00c6fdf7179 100644 --- a/src/stacktraces.cpp +++ b/src/stacktraces.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/stacktraces.h b/src/stacktraces.h index d2e05e7e9d94..152c7699ddad 100644 --- a/src/stacktraces.h +++ b/src/stacktraces.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 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. diff --git a/src/test/bip39_tests.cpp b/src/test/bip39_tests.cpp index 2ccf8ff1a119..186c415d9f3f 100644 --- a/src/test/bip39_tests.cpp +++ b/src/test/bip39_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/cachemap_tests.cpp b/src/test/cachemap_tests.cpp index 59da33c0894a..441f4c9f3fc3 100644 --- a/src/test/cachemap_tests.cpp +++ b/src/test/cachemap_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers #include "cachemap.h" diff --git a/src/test/cachemultimap_tests.cpp b/src/test/cachemultimap_tests.cpp index b1b76f6ed0af..1ae5c334691c 100644 --- a/src/test/cachemultimap_tests.cpp +++ b/src/test/cachemultimap_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers #include "cachemultimap.h" diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp index 40c2eb11a145..ecf78218dbf1 100644 --- a/src/test/evo_deterministicmns_tests.cpp +++ b/src/test/evo_deterministicmns_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2018 The Dash Core developers +// Copyright (c) 2018-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/test/governance_validators_tests.cpp b/src/test/governance_validators_tests.cpp index 89216ec3b2a2..21a951b583ae 100644 --- a/src/test/governance_validators_tests.cpp +++ b/src/test/governance_validators_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers #include "governance/governance-validators.h" #include "utilstrencodings.h" diff --git a/src/test/ratecheck_tests.cpp b/src/test/ratecheck_tests.cpp index e3d96b031144..17016bfe02ec 100644 --- a/src/test/ratecheck_tests.cpp +++ b/src/test/ratecheck_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers #include "governance/governance.h" diff --git a/src/test/test_dash.h b/src/test/test_dash.h index 480c0647031d..eef7dc9ff6d0 100644 --- a/src/test/test_dash.h +++ b/src/test/test_dash.h @@ -1,5 +1,5 @@ // Copyright (c) 2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/uint256.h b/src/uint256.h index 26a14d75c0c2..5409a20a35d1 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/validation.h b/src/validation.h index a0921302eb2a..a6a2b851b945 100644 --- a/src/validation.h +++ b/src/validation.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/version.h b/src/version.h index 148cfd2e3645..def3519381ce 100644 --- a/src/version.h +++ b/src/version.h @@ -1,5 +1,5 @@ // Copyright (c) 2012-2014 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 2ead3d72d4c3..eb744665648c 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 9a63686e7dca..7ace6b8ce9bb 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7d928a3a52a1..c5b28541a812 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2018 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index b7ee76b2fd34..45317aff8653 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1,6 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2015 The Bitcoin Core developers -// Copyright (c) 2014-2017 The Dash Core developers +// Copyright (c) 2014-2019 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. From 9be67220496cc8c8fe68690b59b89ea98ec6d4f5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 1 Sep 2016 12:09:36 +0200 Subject: [PATCH 150/987] Merge #8524: Precompute sighashes 35fe039 Rename to PrecomputedTransactionData (Pieter Wuille) ab48c5e Unit test for sighash caching (Nicolas DORIER) d2c5d04 Precompute sighashes (Pieter Wuille) add missing change from bitcoinconsensus.cpp Signed-off-by: Pasta --- src/script/dashconsensus.cpp | 7 ++++--- src/script/interpreter.cpp | 35 ++++++++++++++++++++++++++++++++-- src/script/interpreter.h | 13 +++++++++++-- src/script/sigcache.h | 2 +- src/test/script_P2SH_tests.cpp | 6 ++++-- src/test/transaction_tests.cpp | 7 +++++-- src/validation.cpp | 20 ++++++++++++------- src/validation.h | 11 +++++++---- 8 files changed, 78 insertions(+), 23 deletions(-) diff --git a/src/script/dashconsensus.cpp b/src/script/dashconsensus.cpp index 7785eb6d9114..2f274dddad84 100644 --- a/src/script/dashconsensus.cpp +++ b/src/script/dashconsensus.cpp @@ -91,10 +91,11 @@ int dashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen) return set_error(err, dashconsensus_ERR_TX_SIZE_MISMATCH); - // Regardless of the verification result, the tx did not error. - set_error(err, dashconsensus_ERR_OK); + // Regardless of the verification result, the tx did not error. + set_error(err, dashconsensus_ERR_OK); - return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn), NULL); + PrecomputedTransactionData txdata(tx); + return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn, txdata), NULL); } catch (const std::exception&) { return set_error(err, dashconsensus_ERR_TX_DESERIALIZE); // Error deserializing } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index bc7e58acdd02..57007d60cd62 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1117,9 +1117,40 @@ class CTransactionSignatureSerializer { } }; +uint256 GetPrevoutHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].prevout; + } + return ss.GetHash(); +} + +uint256 GetSequenceHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vin.size(); n++) { + ss << txTo.vin[n].nSequence; + } + return ss.GetHash(); +} + +uint256 GetOutputsHash(const CTransaction& txTo) { + CHashWriter ss(SER_GETHASH, 0); + for (unsigned int n = 0; n < txTo.vout.size(); n++) { + ss << txTo.vout[n]; + } + return ss.GetHash(); +} + } // anon namespace -uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) +PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo) +{ + hashPrevouts = GetPrevoutHash(txTo); + hashSequence = GetSequenceHash(txTo); + hashOutputs = GetOutputsHash(txTo); +} + +uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const PrecomputedTransactionData* cache) { static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); if (nIn >= txTo.vin.size()) { @@ -1162,7 +1193,7 @@ bool TransactionSignatureChecker::CheckSig(const std::vector& vch int nHashType = vchSig.back(); vchSig.pop_back(); - uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType); + uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, this->txdata); if (!VerifySignature(vchSig, pubkey, sighash)) return false; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index 801e23b361d2..7fd813ca1912 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -94,7 +94,14 @@ enum bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror); -uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType); +struct PrecomputedTransactionData +{ + uint256 hashPrevouts, hashSequence, hashOutputs; + + PrecomputedTransactionData(const CTransaction& tx); +}; + +uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const PrecomputedTransactionData* cache = NULL); class BaseSignatureChecker { @@ -122,12 +129,14 @@ class TransactionSignatureChecker : public BaseSignatureChecker private: const CTransaction* txTo; unsigned int nIn; + const PrecomputedTransactionData* txdata; protected: virtual bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const; public: - TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn) : txTo(txToIn), nIn(nInIn), txdata(NULL) {} + TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), txdata(&txdataIn) {} bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode) const override; bool CheckLockTime(const CScriptNum& nLockTime) const override; bool CheckSequence(const CScriptNum& nSequence) const override; diff --git a/src/script/sigcache.h b/src/script/sigcache.h index d956ba10dd85..bc963067acea 100644 --- a/src/script/sigcache.h +++ b/src/script/sigcache.h @@ -46,7 +46,7 @@ class CachingTransactionSignatureChecker : public TransactionSignatureChecker bool store; public: - CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn), store(storeIn) {} + CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, PrecomputedTransactionData& txdataIn, bool storeIn=true) : TransactionSignatureChecker(txToIn, nInIn, txdataIn), store(storeIn) {} bool VerifySignature(const std::vector& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const override; }; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 1521bb5c2641..894f115127fb 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -104,19 +104,21 @@ BOOST_AUTO_TEST_CASE(sign) } // All of the above should be OK, and the txTos have valid signatures // Check to make sure signature verification fails if we use the wrong ScriptSig: - for (int i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { + PrecomputedTransactionData txdata(txTo[i]); for (int j = 0; j < 8; j++) { CScript sigSave = txTo[i].vin[0].scriptSig; txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig; const CTxOut& output = txFrom.vout[txTo[i].vin[0].prevout.n]; - bool sigOK = CScriptCheck(output.scriptPubKey, output.nValue, txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)(); + bool sigOK = CScriptCheck(output.scriptPubKey, output.nValue, txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)(); if (i == j) BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j)); else BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j)); txTo[i].vin[0].scriptSig = sigSave; } + } } BOOST_AUTO_TEST_CASE(norecurse) diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 50d4e8b2f7b1..3afe38f8affd 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -7,6 +7,7 @@ #include "test/test_dash.h" #include "clientversion.h" +#include "checkqueue.h" #include "consensus/validation.h" #include "core_io.h" #include "key.h" @@ -139,6 +140,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest); BOOST_CHECK(state.IsValid()); + PrecomputedTransactionData txdata(tx); for (unsigned int i = 0; i < tx.vin.size(); i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -149,7 +151,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - verify_flags, TransactionSignatureChecker(&tx, i), &err), + verify_flags, TransactionSignatureChecker(&tx, i, txdata), &err), strTest); BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); } @@ -214,6 +216,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) CValidationState state; fValid = CheckTransaction(tx, state) && state.IsValid(); + PrecomputedTransactionData txdata(tx); for (unsigned int i = 0; i < tx.vin.size() && fValid; i++) { if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout)) @@ -224,7 +227,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) unsigned int verify_flags = ParseScriptFlags(test[2].get_str()); fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], - verify_flags, TransactionSignatureChecker(&tx, i), &err); + verify_flags, TransactionSignatureChecker(&tx, i, txdata), &err); } BOOST_CHECK_MESSAGE(!fValid, strTest); BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err)); diff --git a/src/validation.cpp b/src/validation.cpp index caf93eee8723..a8f292f7d199 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -832,7 +832,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // Check against previous transactions // This is done last to help prevent CPU exhaustion denial-of-service attacks. - if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true)) + PrecomputedTransactionData txdata(tx); + if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata)) return false; // state filled in by CheckInputs // Check again against just the consensus-critical mandatory script @@ -844,7 +845,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // There is a similar check in CreateNewBlock() to prevent creating // invalid blocks, however allowing such transactions into the mempool // can be exploited as a DoS attack. - if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true)) + if (!CheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata)) { return error("%s: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s, %s", __func__, hash.ToString(), FormatStateMessage(state)); @@ -1331,7 +1332,8 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; - if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) { + PrecomputedTransactionData txdata(*ptxTo); + if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, txdata, cacheStore), &error)) { return false; } return true; @@ -1390,7 +1392,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins } }// namespace Consensus -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, std::vector *pvChecks) +bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector *pvChecks) { if (!tx.IsCoinBase()) { @@ -1424,7 +1426,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi const CAmount amount = coin.out.nValue; // Verify signature - CScriptCheck check(scriptPubKey, amount, tx, i, flags, cacheStore); + CScriptCheck check(scriptPubKey, amount, tx, i, flags, cacheStore, &txdata); if (pvChecks) { pvChecks->push_back(CScriptCheck()); check.swap(pvChecks->back()); @@ -1437,7 +1439,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi // avoid splitting the network between upgraded and // non-upgraded nodes. CScriptCheck check2(scriptPubKey, amount, tx, i, - flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore); + flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &txdata); if (check2()) return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } @@ -2015,6 +2017,9 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd std::vector > addressUnspentIndex; std::vector > spentIndex; + std::vector txdata; + txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated + bool fDIP0001Active_context = pindex->nHeight >= Params().GetConsensus().DIP0001Height; for (unsigned int i = 0; i < block.vtx.size(); i++) @@ -2028,6 +2033,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd return state.DoS(100, error("ConnectBlock(): too many sigops"), REJECT_INVALID, "bad-blk-sigops"); + txdata.emplace_back(tx); if (!tx.IsCoinBase()) { if (!view.HaveInputs(tx)) @@ -2102,7 +2108,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd std::vector vChecks; bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */ - if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, nScriptCheckThreads ? &vChecks : NULL)) + if (!CheckInputs(tx, state, view, fScriptChecks, flags, fCacheResults, txdata[i], nScriptCheckThreads ? &vChecks : NULL)) return error("ConnectBlock(): CheckInputs on %s failed with %s", tx.GetHash().ToString(), FormatStateMessage(state)); control.Add(vChecks); diff --git a/src/validation.h b/src/validation.h index cab4ed6c1686..f45a97cbd14a 100644 --- a/src/validation.h +++ b/src/validation.h @@ -46,6 +46,7 @@ class CBlockPolicyEstimator; class CTxMemPool; class CValidationInterface; class CValidationState; +class PrecomputedTransactionData; struct ChainTxData; struct LockPoints; @@ -233,7 +234,7 @@ static const uint64_t MIN_DISK_SPACE_FOR_BLOCK_FILES = 945 * 1024 * 1024; * * Note that we guarantee that either the proof-of-work is valid on pblock, or * (and possibly also) BlockChecked will have been called. - * + * * Call without cs_main held. * * @param[in] pblock The block we want to process. @@ -377,7 +378,7 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma * instead of being performed inline. */ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, - unsigned int flags, bool cacheStore, std::vector *pvChecks = NULL); + unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector *pvChecks = NULL); /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); @@ -450,12 +451,13 @@ class CScriptCheck unsigned int nFlags; bool cacheStore; ScriptError error; + PrecomputedTransactionData *txdata; public: CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {} - CScriptCheck(const CScript& scriptPubKeyIn, const CAmount amountIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : + CScriptCheck(const CScript& scriptPubKeyIn, const CAmount amountIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) : scriptPubKey(scriptPubKeyIn), - ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { } + ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { } bool operator()(); @@ -466,6 +468,7 @@ class CScriptCheck std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); std::swap(error, check.error); + std::swap(txdata, check.txdata); } ScriptError GetScriptError() const { return error; } From 131e94ef2176037cee666da4f05617fb283f67da Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 6 Jun 2017 17:36:58 +0200 Subject: [PATCH 151/987] Merge #10201: pass Consensus::Params& to functions in validation.cpp and make them static 24980a3 Make functions in validation.cpp static and pass chainparams (Mario Dian) Tree-SHA512: 2d1b7b0ffd851317ed522911c1b6592855376c5cbc65d71ec0f8aa507eb6caef21b0709b3692255f1d719662db7447579c10df02f6ef4cd35fcb0bdf2e653af6 fix Signed-off-by: Pasta add param Signed-off-by: Pasta --- src/validation.cpp | 104 +++++++++++++++++++++++++++++---------------- src/validation.h | 42 +----------------- 2 files changed, 68 insertions(+), 78 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index a8f292f7d199..ef1979a40621 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -205,8 +205,11 @@ enum FlushStateMode { }; // See definition for documentation -bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0); -void FindFilesToPruneManual(std::set& setFilesToPrune, int nManualPruneHeight); +static bool FlushStateToDisk(const CChainParams& chainParams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0); +static void FindFilesToPruneManual(std::set& setFilesToPrune, int nManualPruneHeight); +static void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight); +static bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector *pvChecks = NULL); +static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) { @@ -424,7 +427,6 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool return EvaluateSequenceLocks(index, lockPair); } - unsigned int GetLegacySigOpCount(const CTransaction& tx) { unsigned int nSigOps = 0; @@ -573,7 +575,7 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state, return true; } -void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) { +static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) { int expired = pool.Expire(GetTime() - age); if (expired != 0) { LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired); @@ -606,7 +608,7 @@ static bool IsCurrentForFeeEstimation() return true; } -bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree, +static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree, bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount& nAbsurdFee, std::vector& coins_to_uncache, bool fDryRun) { @@ -883,12 +885,13 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C return true; } -bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, +/** (try to) add transaction to memory pool with a specified acceptance time **/ +static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, const CAmount nAbsurdFee, bool fDryRun) { std::vector coins_to_uncache; - bool res = AcceptToMemoryPoolWorker(pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, fDryRun); + bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, fDryRun); if (!res || fDryRun) { if(!res) LogPrint(BCLog::MEMPOOL, "%s: %s %s (%s)\n", __func__, tx->GetHash().ToString(), state.GetRejectReason(), state.GetDebugMessage()); BOOST_FOREACH(const COutPoint& hashTx, coins_to_uncache) @@ -896,14 +899,15 @@ bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const } // After we've (potentially) uncached entries, ensure our coins cache is still within its size limits CValidationState stateDummy; - FlushStateToDisk(stateDummy, FLUSH_STATE_PERIODIC); + FlushStateToDisk(chainparams, stateDummy, FLUSH_STATE_PERIODIC); return res; } bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, bool* pfMissingInputs, bool fOverrideMempoolLimit, const CAmount nAbsurdFee, bool fDryRun) { - return AcceptToMemoryPoolWithTime(pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), fOverrideMempoolLimit, nAbsurdFee, fDryRun); + const CChainParams& chainparams = Params(); + return AcceptToMemoryPoolWithTime(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, GetTime(), fOverrideMempoolLimit, nAbsurdFee, fDryRun); } bool GetTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector &hashes) @@ -1024,7 +1028,7 @@ bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus // CBlock and CBlockIndex // -bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) +static bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart) { // Open history file to append CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); @@ -1202,7 +1206,7 @@ bool IsInitialBlockDownload() CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL; -void CheckForkWarningConditions() +static void CheckForkWarningConditions() { AssertLockHeld(cs_main); // Before we get past initial download, we cannot reliably alert about forks @@ -1250,7 +1254,7 @@ void CheckForkWarningConditions() } } -void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) +static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) { AssertLockHeld(cs_main); // If we are on a fork that is sufficiently large, set a warning flag @@ -1392,7 +1396,12 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins } }// namespace Consensus -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector *pvChecks) +/** + * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) + * This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it + * instead of being performed inline. + */ +static bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector *pvChecks) { if (!tx.IsCoinBase()) { @@ -1768,7 +1777,7 @@ void static FlushBlockFile(bool fFinalize = false) } } -bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); +static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize); static CCheckQueue scriptcheckqueue(128); @@ -2322,9 +2331,8 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd * if they're too large, if it's been a while since the last write, * or always and in all cases if we're in prune mode and are deleting files. */ -bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight) { +bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState &state, FlushStateMode mode, int nManualPruneHeight) { int64_t nMempoolUsage = mempool.DynamicMemoryUsage(); - const CChainParams& chainparams = Params(); LOCK2(cs_main, cs_LastBlockFile); static int64_t nLastWrite = 0; static int64_t nLastFlush = 0; @@ -2431,13 +2439,15 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int n void FlushStateToDisk() { CValidationState state; - FlushStateToDisk(state, FLUSH_STATE_ALWAYS); + const CChainParams& chainparams = Params(); + FlushStateToDisk(chainparams, state, FLUSH_STATE_ALWAYS); } void PruneAndFlush() { CValidationState state; fCheckForPruning = true; - FlushStateToDisk(state, FLUSH_STATE_NONE); + const CChainParams& chainparams = Params(); + FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); } /** Update chainActive and related internal data structures. */ @@ -2526,7 +2536,7 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara } LogPrint(BCLog::BENCHMARK, "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); // Write the chain state to disk, if necessary. - if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) + if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED)) return false; // Resurrect mempool transactions from the disconnected block. std::vector vHashUpdate; @@ -2670,7 +2680,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3; LogPrint(BCLog::BENCHMARK, " - Flush: %.2fms [%.2fs]\n", (nTime4 - nTime3) * 0.001, nTimeFlush * 0.000001); // Write the chain state to disk, if necessary. - if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) + if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED)) return false; int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4; LogPrint(BCLog::BENCHMARK, " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); @@ -2970,7 +2980,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, CheckBlockIndex(chainparams.GetConsensus()); // Write changes periodically to disk, after relay. - if (!FlushStateToDisk(state, FLUSH_STATE_PERIODIC)) { + if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_PERIODIC)) { return false; } @@ -3090,7 +3100,7 @@ bool ResetBlockFailureFlags(CBlockIndex *pindex) { return true; } -CBlockIndex* AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus = BLOCK_VALID_TREE) +static CBlockIndex* AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus = BLOCK_VALID_TREE) { // Check for duplicate uint256 hash = block.GetHash(); @@ -3181,7 +3191,7 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl return true; } -bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) +static bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAddSize, unsigned int nHeight, uint64_t nTime, bool fKnown = false) { LOCK(cs_LastBlockFile); @@ -3238,7 +3248,7 @@ bool FindBlockPos(CValidationState &state, CDiskBlockPos &pos, unsigned int nAdd return true; } -bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize) +static bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigned int nAddSize) { pos.nFile = nFile; @@ -3269,7 +3279,7 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne return true; } -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW) +static bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true) { // Check proof of work matches claimed amount if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) @@ -3364,7 +3374,10 @@ static bool CheckIndexAgainstCheckpoint(const CBlockIndex* pindexPrev, CValidati return true; } -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) +/** Context-dependent validity checks. + * By "context", we mean only the previous block headers, but not the UTXO + * set; UTXO-related validity checks are done in ConnectBlock(). */ +static bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) { assert(pindexPrev != NULL); const int nHeight = pindexPrev->nHeight + 1; @@ -3401,7 +3414,7 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta return true; } -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) +static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { const int nHeight = pindexPrev == NULL ? 0 : pindexPrev->nHeight + 1; @@ -3621,7 +3634,7 @@ static bool AcceptBlock(const std::shared_ptr& pblock, CValidation } if (fCheckForPruning) - FlushStateToDisk(state, FLUSH_STATE_NONE); // we just allocated more disk space for block files + FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); // we just allocated more disk space for block files return true; } @@ -3701,7 +3714,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, */ /* Calculate the amount of disk space the block & undo files currently use */ -uint64_t CalculateCurrentUsage() +static uint64_t CalculateCurrentUsage() { uint64_t retval = 0; BOOST_FOREACH(const CBlockFileInfo &file, vinfoBlockFile) { @@ -3754,7 +3767,7 @@ void UnlinkPrunedFiles(const std::set& setFilesToPrune) } /* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */ -void FindFilesToPruneManual(std::set& setFilesToPrune, int nManualPruneHeight) +static void FindFilesToPruneManual(std::set& setFilesToPrune, int nManualPruneHeight) { assert(fPruneMode && nManualPruneHeight > 0); @@ -3779,11 +3792,26 @@ void FindFilesToPruneManual(std::set& setFilesToPrune, int nManualPruneHeig void PruneBlockFilesManual(int nManualPruneHeight) { CValidationState state; - FlushStateToDisk(state, FLUSH_STATE_NONE, nManualPruneHeight); + const CChainParams& chainparams = Params(); + FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE, nManualPruneHeight); } -/* Calculate the block/rev files that should be deleted to remain under target*/ -void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight) +/** + * Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a user-defined target. + * The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new + * space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex + * (which in this case means the blockchain must be re-downloaded.) + * + * Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set. + * Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.) + * Pruning cannot take place until the longest chain is at least a certain length (100000 on mainnet, 1000 on testnet, 1000 on regtest). + * Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip. + * The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files. + * A db flag records the fact that at least some block files have been pruned. + * + * @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned + */ +static void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight) { LOCK2(cs_main, cs_LastBlockFile); if (chainActive.Tip() == NULL || nPruneTarget == 0) { @@ -3841,7 +3869,7 @@ bool CheckDiskSpace(uint64_t nAdditionalBytes) return true; } -FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) +static FILE* OpenDiskFile(const CDiskBlockPos &pos, const char *prefix, bool fReadOnly) { if (pos.IsNull()) return NULL; @@ -3868,7 +3896,8 @@ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "blk", fReadOnly); } -FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { +/** Open an undo file (rev?????.dat) */ +static FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly) { return OpenDiskFile(pos, "rev", fReadOnly); } @@ -4227,7 +4256,7 @@ bool InitBlockIndex(const CChainParams& chainparams) } // Force a chainstate write so that when we VerifyDB in a moment, it doesn't check stale data - return FlushStateToDisk(state, FLUSH_STATE_ALWAYS); + return FlushStateToDisk(chainparams, state, FLUSH_STATE_ALWAYS); } catch (const std::runtime_error& e) { return error("%s: failed to initialize block database: %s", __func__, e.what()); } @@ -4568,6 +4597,7 @@ bool LoadMempool(void) return true; } + const CChainParams& chainparams = Params(); int64_t nExpiryTimeout = GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb"); CAutoFile file(filestr, SER_DISK, CLIENT_VERSION); @@ -4604,7 +4634,7 @@ bool LoadMempool(void) CValidationState state; if (nTime + nExpiryTimeout > nNow) { LOCK(cs_main); - AcceptToMemoryPoolWithTime(mempool, state, tx, true, NULL, nTime); + AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, true, NULL, nTime, NULL, false, 0); if (state.IsValid()) { ++count; } else { diff --git a/src/validation.h b/src/validation.h index f45a97cbd14a..4135807e2470 100644 --- a/src/validation.h +++ b/src/validation.h @@ -260,8 +260,6 @@ bool ProcessNewBlockHeaders(const std::vector& block, CValidationS bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); /** Open a block file (blk?????.dat) */ FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false); -/** Open an undo file (rev?????.dat) */ -FILE* OpenUndoFile(const CDiskBlockPos &pos, bool fReadOnly = false); /** Translation to a filesystem path */ fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix); /** Import blocks from an external file */ @@ -296,23 +294,6 @@ CAmount GetMasternodePayment(int nHeight, CAmount blockValue); /** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */ double GuessVerificationProgress(const ChainTxData& data, CBlockIndex* pindex); -/** - * Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a user-defined target. - * The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new - * space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex - * (which in this case means the blockchain must be re-downloaded.) - * - * Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set. - * Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.) - * Pruning cannot take place until the longest chain is at least a certain length (100000 on mainnet, 1000 on testnet, 1000 on regtest). - * Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip. - * The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files. - * A db flag records the fact that at least some block files have been pruned. - * - * @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned - */ -void FindFilesToPrune(std::set& setFilesToPrune, uint64_t nPruneAfterHeight); - /** * Mark one block file as pruned. */ @@ -337,11 +318,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa bool* pfMissingInputs, bool fOverrideMempoolLimit=false, const CAmount nAbsurdFee=0, bool fDryRun=false); -/** (try to) add transaction to memory pool with a specified acceptance time **/ -bool AcceptToMemoryPoolWithTime(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree, - bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit=false, - const CAmount nAbsurdFee=0, bool fDryRun=false); - bool GetUTXOCoin(const COutPoint& outpoint, Coin& coin); int GetUTXOHeight(const COutPoint& outpoint); int GetUTXOConfirmations(const COutPoint& outpoint); @@ -364,7 +340,7 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx); /** * Count ECDSA signature operations in pay-to-script-hash inputs. - * + * * @param[in] mapInputs Map of previous transactions that have outputs we're spending * @return maximum number of sigops required to validate this transaction's inputs * @see CTransaction::FetchInputs @@ -372,14 +348,6 @@ unsigned int GetLegacySigOpCount(const CTransaction& tx); unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs); -/** - * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) - * This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it - * instead of being performed inline. - */ -bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, - unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, std::vector *pvChecks = NULL); - /** Apply the effects of this transaction on the UTXO set represented by view */ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight); @@ -483,7 +451,6 @@ bool GetAddressUnspent(uint160 addressHash, int type, std::vector > &unspentOutputs); /** Functions for disk access for blocks */ -bool WriteBlockToDisk(const CBlock& block, CDiskBlockPos& pos, const CMessageHeader::MessageStartChars& messageStart); bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos, const Consensus::Params& consensusParams); bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams); @@ -494,15 +461,8 @@ bool DisconnectBlocks(int blocks); void ReprocessBlocks(int nBlocks); /** Context-independent validity checks */ -bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true); bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true); -/** Context-dependent validity checks. - * By "context", we mean only the previous block headers, but not the UTXO - * set; UTXO-related validity checks are done in ConnectBlock(). */ -bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev, int64_t nAdjustedTime); -bool ContextualCheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex *pindexPrev); - /** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); From 864856688dd9b1488daa6fe500edc37dd5a0a571 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Thu, 13 Jun 2019 11:01:26 +0200 Subject: [PATCH 152/987] Multiple speed optimizations for deterministic MN list handling (#2972) * Generalize CBLSLazyWrapper so that it can be used of pubkeys and secret keys * Implement == and != operators for CBLSLazyWrapper * Implement cached hash for CBLSLazyWrapper * Use CBLSLazyPublicKey for CDeterministicMNState::pubKeyOperator * Speed up GetProjectedMNPayees by sorting the MN list by last paid Instead of updating a temporary list for each projected height and calling GetMNPayee() on it. * Cache intermediate lists in GetListForBlock This avoids re-loading and applying diffs again and again. * Only update masternode list UI max once every 3 seconds This avoids updating the UI on every block, which turned out to be very expensive. * Fix compilation * Drop time restrictions for mn list update in ClientModel They are fully handled by MasternodeList now. --- src/bls/bls.cpp | 27 ------- src/bls/bls.h | 107 +++++++++++++++++++++---- src/evo/deterministicmns.cpp | 43 +++++----- src/evo/deterministicmns.h | 6 +- src/evo/mnauth.cpp | 2 +- src/evo/providertx.cpp | 4 +- src/evo/simplifiedmns.cpp | 4 +- src/evo/simplifiedmns.h | 2 +- src/governance/governance-object.cpp | 4 +- src/governance/governance-vote.cpp | 2 +- src/instantsend.cpp | 2 +- src/llmq/quorums_chainlocks.cpp | 2 +- src/llmq/quorums_commitment.cpp | 2 +- src/llmq/quorums_dkgsession.cpp | 4 +- src/llmq/quorums_dkgsessionhandler.cpp | 4 +- src/llmq/quorums_instantsend.cpp | 4 +- src/llmq/quorums_signing.cpp | 8 +- src/llmq/quorums_signing_shares.cpp | 12 +-- src/net_processing.cpp | 2 +- src/privatesend/privatesend-client.cpp | 2 +- src/privatesend/privatesend-server.cpp | 2 +- src/qt/clientmodel.cpp | 9 +-- src/qt/masternodelist.cpp | 49 +++++++---- src/qt/masternodelist.h | 9 ++- src/rpc/masternode.cpp | 6 +- src/rpc/rpcevo.cpp | 6 +- src/test/evo_simplifiedmns_tests.cpp | 2 +- src/txmempool.cpp | 8 +- 28 files changed, 197 insertions(+), 137 deletions(-) diff --git a/src/bls/bls.cpp b/src/bls/bls.cpp index f6d06ae7fecc..94ec11bcbb85 100644 --- a/src/bls/bls.cpp +++ b/src/bls/bls.cpp @@ -424,33 +424,6 @@ bool CBLSSignature::Recover(const std::vector& sigs, const std::v } #ifndef BUILD_BITCOIN_INTERNAL -void CBLSLazySignature::SetSig(const CBLSSignature& _sig) -{ - std::unique_lock l(mutex); - bufValid = false; - sigInitialized = true; - sig = _sig; -} - -const CBLSSignature& CBLSLazySignature::GetSig() const -{ - std::unique_lock l(mutex); - static CBLSSignature invalidSig; - if (!bufValid && !sigInitialized) { - return invalidSig; - } - if (!sigInitialized) { - sig.SetBuf(buf, sizeof(buf)); - if (!sig.CheckMalleable(buf, sizeof(buf))) { - bufValid = false; - sigInitialized = false; - sig = invalidSig; - } else { - sigInitialized = true; - } - } - return sig; -} static std::once_flag init_flag; static mt_pooled_secure_allocator* secure_allocator_instance; diff --git a/src/bls/bls.h b/src/bls/bls.h index 5f1c58c44e78..4d5881f4c659 100644 --- a/src/bls/bls.h +++ b/src/bls/bls.h @@ -310,29 +310,34 @@ class CBLSSignature : public CBLSWrapper +class CBLSLazyWrapper { private: mutable std::mutex mutex; - mutable char buf[BLS_CURVE_SIG_SIZE]; + mutable char buf[BLSObject::SerSize]; mutable bool bufValid{false}; - mutable CBLSSignature sig; - mutable bool sigInitialized{false}; + mutable BLSObject obj; + mutable bool objInitialized{false}; + + mutable uint256 hash; public: - CBLSLazySignature() + CBLSLazyWrapper() { memset(buf, 0, sizeof(buf)); + // the all-zero buf is considered a valid buf, but the resulting object will return false for IsValid + bufValid = true; } - CBLSLazySignature(const CBLSLazySignature& r) + CBLSLazyWrapper(const CBLSLazyWrapper& r) { *this = r; } - CBLSLazySignature& operator=(const CBLSLazySignature& r) + CBLSLazyWrapper& operator=(const CBLSLazyWrapper& r) { std::unique_lock l(r.mutex); bufValid = r.bufValid; @@ -341,12 +346,13 @@ class CBLSLazySignature } else { memset(buf, 0, sizeof(buf)); } - sigInitialized = r.sigInitialized; - if (r.sigInitialized) { - sig = r.sig; + objInitialized = r.objInitialized; + if (r.objInitialized) { + obj = r.obj; } else { - sig.Reset(); + obj.Reset(); } + hash = r.hash; return *this; } @@ -354,12 +360,13 @@ class CBLSLazySignature inline void Serialize(Stream& s) const { std::unique_lock l(mutex); - if (!sigInitialized && !bufValid) { - throw std::ios_base::failure("sig and buf not initialized"); + if (!objInitialized && !bufValid) { + throw std::ios_base::failure("obj and buf not initialized"); } if (!bufValid) { - sig.GetBuf(buf, sizeof(buf)); + obj.GetBuf(buf, sizeof(buf)); bufValid = true; + hash = uint256(); } s.write(buf, sizeof(buf)); } @@ -370,12 +377,78 @@ class CBLSLazySignature std::unique_lock l(mutex); s.read(buf, sizeof(buf)); bufValid = true; - sigInitialized = false; + objInitialized = false; + hash = uint256(); + } + + void Set(const BLSObject& _obj) + { + std::unique_lock l(mutex); + bufValid = false; + objInitialized = true; + obj = _obj; + hash = uint256(); + } + const BLSObject& Get() const + { + std::unique_lock l(mutex); + static BLSObject invalidObj; + if (!bufValid && !objInitialized) { + return invalidObj; + } + if (!objInitialized) { + obj.SetBuf(buf, sizeof(buf)); + if (!obj.CheckMalleable(buf, sizeof(buf))) { + bufValid = false; + objInitialized = false; + obj = invalidObj; + } else { + objInitialized = true; + } + } + return obj; } - void SetSig(const CBLSSignature& _sig); - const CBLSSignature& GetSig() const; + bool operator==(const CBLSLazyWrapper& r) const + { + if (bufValid && r.bufValid) { + return memcmp(buf, r.buf, sizeof(buf)) == 0; + } + if (objInitialized && r.objInitialized) { + return obj == r.obj; + } + return Get() == r.Get(); + } + + bool operator!=(const CBLSLazyWrapper& r) const + { + return !(*this == r); + } + + uint256 GetHash() const + { + std::unique_lock l(mutex); + if (!bufValid) { + obj.GetBuf(buf, sizeof(buf)); + bufValid = true; + hash = uint256(); + } + if (hash.IsNull()) { + UpdateHash(); + } + return hash; + } +private: + void UpdateHash() const + { + CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); + ss.write(buf, sizeof(buf)); + hash = ss.GetHash(); + } }; +typedef CBLSLazyWrapper CBLSLazySignature; +typedef CBLSLazyWrapper CBLSLazyPublicKey; +typedef CBLSLazyWrapper CBLSLazySecretKey; #endif typedef std::vector BLSIdVector; diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 0cfaab4e3fab..f5e3fc036801 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -38,7 +38,7 @@ std::string CDeterministicMNState::ToString() const return strprintf("CDeterministicMNState(nRegisteredHeight=%d, nLastPaidHeight=%d, nPoSePenalty=%d, nPoSeRevivedHeight=%d, nPoSeBanHeight=%d, nRevocationReason=%d, " "ownerAddress=%s, pubKeyOperator=%s, votingAddress=%s, addr=%s, payoutAddress=%s, operatorPayoutAddress=%s)", nRegisteredHeight, nLastPaidHeight, nPoSePenalty, nPoSeRevivedHeight, nPoSeBanHeight, nRevocationReason, - CBitcoinAddress(keyIDOwner).ToString(), pubKeyOperator.ToString(), CBitcoinAddress(keyIDVoting).ToString(), addr.ToStringIPPort(false), payoutAddress, operatorPayoutAddress); + CBitcoinAddress(keyIDOwner).ToString(), pubKeyOperator.Get().ToString(), CBitcoinAddress(keyIDVoting).ToString(), addr.ToStringIPPort(false), payoutAddress, operatorPayoutAddress); } void CDeterministicMNState::ToJson(UniValue& obj) const @@ -60,7 +60,7 @@ void CDeterministicMNState::ToJson(UniValue& obj) const CBitcoinAddress payoutAddress(dest); obj.push_back(Pair("payoutAddress", payoutAddress.ToString())); } - obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); + obj.push_back(Pair("pubKeyOperator", pubKeyOperator.Get().ToString())); if (ExtractDestination(scriptOperatorPayout, dest)) { CBitcoinAddress operatorPayoutAddress(dest); obj.push_back(Pair("operatorPayoutAddress", operatorPayoutAddress.ToString())); @@ -147,7 +147,7 @@ CDeterministicMNCPtr CDeterministicMNList::GetValidMN(const uint256& proTxHash) CDeterministicMNCPtr CDeterministicMNList::GetMNByOperatorKey(const CBLSPublicKey& pubKey) { for (const auto& p : mnMap) { - if (p.second->pdmnState->pubKeyOperator == pubKey) { + if (p.second->pdmnState->pubKeyOperator.Get() == pubKey) { return p.second; } } @@ -217,21 +217,21 @@ CDeterministicMNCPtr CDeterministicMNList::GetMNPayee() const std::vector CDeterministicMNList::GetProjectedMNPayees(int nCount) const { + if (nCount > GetValidMNsCount()) { + nCount = GetValidMNsCount(); + } + std::vector result; result.reserve(nCount); - CDeterministicMNList tmpMNList = *this; - for (int h = nHeight; h < nHeight + nCount; h++) { - tmpMNList.SetHeight(h); - - CDeterministicMNCPtr payee = tmpMNList.GetMNPayee(); - // push the original MN object instead of the one from the temporary list - result.push_back(GetMN(payee->proTxHash)); + ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) { + result.emplace_back(dmn); + }); + std::sort(result.begin(), result.end(), [&](const CDeterministicMNCPtr& a, const CDeterministicMNCPtr& b) { + return CompareByLastPaid(a, b); + }); - CDeterministicMNStatePtr newState = std::make_shared(*payee->pdmnState); - newState->nLastPaidHeight = h; - tmpMNList.UpdateMN(payee->proTxHash, newState); - } + result.resize(nCount); return result; } @@ -420,7 +420,7 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn) AddUniqueProperty(dmn, dmn->pdmnState->addr); } AddUniqueProperty(dmn, dmn->pdmnState->keyIDOwner); - if (dmn->pdmnState->pubKeyOperator.IsValid()) { + if (dmn->pdmnState->pubKeyOperator.Get().IsValid()) { AddUniqueProperty(dmn, dmn->pdmnState->pubKeyOperator); } } @@ -448,7 +448,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash) DeleteUniqueProperty(dmn, dmn->pdmnState->addr); } DeleteUniqueProperty(dmn, dmn->pdmnState->keyIDOwner); - if (dmn->pdmnState->pubKeyOperator.IsValid()) { + if (dmn->pdmnState->pubKeyOperator.Get().IsValid()) { DeleteUniqueProperty(dmn, dmn->pdmnState->pubKeyOperator); } mnMap = mnMap.erase(proTxHash); @@ -692,7 +692,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C if (newState->nPoSeBanHeight != -1) { // only revive when all keys are set - if (newState->pubKeyOperator.IsValid() && !newState->keyIDVoting.IsNull() && !newState->keyIDOwner.IsNull()) { + if (newState->pubKeyOperator.Get().IsValid() && !newState->keyIDVoting.IsNull() && !newState->keyIDOwner.IsNull()) { newState->nPoSePenalty = 0; newState->nPoSeBanHeight = -1; newState->nPoSeRevivedHeight = nHeight; @@ -720,12 +720,12 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C return _state.DoS(100, false, REJECT_INVALID, "bad-protx-hash"); } auto newState = std::make_shared(*dmn->pdmnState); - if (newState->pubKeyOperator != proTx.pubKeyOperator) { + if (newState->pubKeyOperator.Get() != proTx.pubKeyOperator) { // reset all operator related fields and put MN into PoSe-banned state in case the operator key changes newState->ResetOperatorFields(); newState->BanIfNotBanned(nHeight); } - newState->pubKeyOperator = proTx.pubKeyOperator; + newState->pubKeyOperator.Set(proTx.pubKeyOperator); newState->keyIDVoting = proTx.keyIDVoting; newState->scriptPayout = proTx.scriptPayout; @@ -857,12 +857,14 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlock(const uint256& blo } if (evoDb.Read(std::make_pair(DB_LIST_SNAPSHOT, blockHashTmp), snapshot)) { + mnListsCache.emplace(blockHashTmp, snapshot); break; } CDeterministicMNListDiff diff; if (!evoDb.Read(std::make_pair(DB_LIST_DIFF, blockHashTmp), diff)) { snapshot = CDeterministicMNList(blockHashTmp, -1); + mnListsCache.emplace(blockHashTmp, snapshot); break; } @@ -877,9 +879,10 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlock(const uint256& blo snapshot.SetBlockHash(diff.blockHash); snapshot.SetHeight(diff.nHeight); } + + mnListsCache.emplace(diff.blockHash, snapshot); } - mnListsCache.emplace(blockHash, snapshot); return snapshot; } diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 1e9e9725d26e..286ef7023b0a 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -44,7 +44,7 @@ class CDeterministicMNState uint256 confirmedHashWithProRegTxHash; CKeyID keyIDOwner; - CBLSPublicKey pubKeyOperator; + CBLSLazyPublicKey pubKeyOperator; CKeyID keyIDVoting; CService addr; CScript scriptPayout; @@ -55,7 +55,7 @@ class CDeterministicMNState CDeterministicMNState(const CProRegTx& proTx) { keyIDOwner = proTx.keyIDOwner; - pubKeyOperator = proTx.pubKeyOperator; + pubKeyOperator.Set(proTx.pubKeyOperator); keyIDVoting = proTx.keyIDVoting; addr = proTx.addr; scriptPayout = proTx.scriptPayout; @@ -89,7 +89,7 @@ class CDeterministicMNState void ResetOperatorFields() { - pubKeyOperator = CBLSPublicKey(); + pubKeyOperator.Set(CBLSPublicKey()); addr = CService(); scriptOperatorPayout = CScript(); nRevocationReason = CProUpRevTx::REASON_NOT_SPECIFIED; diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index be2ce65c000b..5ac3e43807bb 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -89,7 +89,7 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS signHash = ::SerializeHash(std::make_tuple(dmn->pdmnState->pubKeyOperator, pnode->sentMNAuthChallenge, !pnode->fInbound)); } - if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator, signHash)) { + if (!mnauth.sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), signHash)) { LOCK(cs_main); // Same as above, MN seems to not know about his fate yet, so give him a chance to update. If this is a // malicious actor (DoSing us), we'll ban him soon. diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp index 5db4dda4cdbb..7dc094ce628f 100644 --- a/src/evo/providertx.cpp +++ b/src/evo/providertx.cpp @@ -257,7 +257,7 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa if (!CheckInputsHash(tx, ptx, state)) { return false; } - if (!CheckHashSig(ptx, mn->pdmnState->pubKeyOperator, state)) { + if (!CheckHashSig(ptx, mn->pdmnState->pubKeyOperator.Get(), state)) { return false; } } @@ -376,7 +376,7 @@ bool CheckProUpRevTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal if (!CheckInputsHash(tx, ptx, state)) return false; - if (!CheckHashSig(ptx, dmn->pdmnState->pubKeyOperator, state)) + if (!CheckHashSig(ptx, dmn->pdmnState->pubKeyOperator.Get(), state)) return false; } diff --git a/src/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index d43b71741acd..d23e0f9ce7d6 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -37,7 +37,7 @@ uint256 CSimplifiedMNListEntry::CalcHash() const std::string CSimplifiedMNListEntry::ToString() const { return strprintf("CSimplifiedMNListEntry(proRegTxHash=%s, confirmedHash=%s, service=%s, pubKeyOperator=%s, votingAddress=%s, isValid=%d)", - proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(false), pubKeyOperator.ToString(), CBitcoinAddress(keyIDVoting).ToString(), isValid); + proRegTxHash.ToString(), confirmedHash.ToString(), service.ToString(false), pubKeyOperator.Get().ToString(), CBitcoinAddress(keyIDVoting).ToString(), isValid); } void CSimplifiedMNListEntry::ToJson(UniValue& obj) const @@ -47,7 +47,7 @@ void CSimplifiedMNListEntry::ToJson(UniValue& obj) const obj.push_back(Pair("proRegTxHash", proRegTxHash.ToString())); obj.push_back(Pair("confirmedHash", confirmedHash.ToString())); obj.push_back(Pair("service", service.ToString(false))); - obj.push_back(Pair("pubKeyOperator", pubKeyOperator.ToString())); + obj.push_back(Pair("pubKeyOperator", pubKeyOperator.Get().ToString())); obj.push_back(Pair("votingAddress", CBitcoinAddress(keyIDVoting).ToString())); obj.push_back(Pair("isValid", isValid)); } diff --git a/src/evo/simplifiedmns.h b/src/evo/simplifiedmns.h index bf67043f7fc2..7a642b29af76 100644 --- a/src/evo/simplifiedmns.h +++ b/src/evo/simplifiedmns.h @@ -27,7 +27,7 @@ class CSimplifiedMNListEntry uint256 proRegTxHash; uint256 confirmedHash; CService service; - CBLSPublicKey pubKeyOperator; + CBLSLazyPublicKey pubKeyOperator; CKeyID keyIDVoting; bool isValid; diff --git a/src/governance/governance-object.cpp b/src/governance/governance-object.cpp index 96def5a73b50..63c2793e0840 100644 --- a/src/governance/governance-object.cpp +++ b/src/governance/governance-object.cpp @@ -490,8 +490,8 @@ bool CGovernanceObject::IsValidLocally(std::string& strError, bool& fMissingConf } // Check that we have a valid MN signature - if (!CheckSignature(dmn->pdmnState->pubKeyOperator)) { - strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey = " + dmn->pdmnState->pubKeyOperator.ToString(); + if (!CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { + strError = "Invalid masternode signature for: " + strOutpoint + ", pubkey = " + dmn->pdmnState->pubKeyOperator.Get().ToString(); return false; } diff --git a/src/governance/governance-vote.cpp b/src/governance/governance-vote.cpp index 5836e78a9fb6..9a7855d232d9 100644 --- a/src/governance/governance-vote.cpp +++ b/src/governance/governance-vote.cpp @@ -280,7 +280,7 @@ bool CGovernanceVote::IsValid(bool useVotingKey) const if (useVotingKey) { return CheckSignature(dmn->pdmnState->keyIDVoting); } else { - return CheckSignature(dmn->pdmnState->pubKeyOperator); + return CheckSignature(dmn->pdmnState->pubKeyOperator.Get()); } } diff --git a/src/instantsend.cpp b/src/instantsend.cpp index ff5bf3d7df47..4e91fb425ecb 100644 --- a/src/instantsend.cpp +++ b/src/instantsend.cpp @@ -1124,7 +1124,7 @@ bool CTxLockVote::CheckSignature() const CBLSSignature sig; sig.SetBuf(vchMasternodeSignature); - if (!sig.IsValid() || !sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator, hash)) { + if (!sig.IsValid() || !sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), hash)) { LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); return false; } diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 827730d72784..78ad22e8f524 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -571,7 +571,7 @@ void CChainLocksHandler::HandleNewRecoveredSig(const llmq::CRecoveredSig& recove clsig.nHeight = lastSignedHeight; clsig.blockHash = lastSignedMsgHash; - clsig.sig = recoveredSig.sig.GetSig(); + clsig.sig = recoveredSig.sig.Get(); } ProcessNewChainLock(-1, clsig, ::SerializeHash(clsig)); } diff --git a/src/llmq/quorums_commitment.cpp b/src/llmq/quorums_commitment.cpp index 1d7d38fd31d0..c75cd754b460 100644 --- a/src/llmq/quorums_commitment.cpp +++ b/src/llmq/quorums_commitment.cpp @@ -86,7 +86,7 @@ bool CFinalCommitment::Verify(const std::vector& members, if (!signers[i]) { continue; } - memberPubKeys.emplace_back(members[i]->pdmnState->pubKeyOperator); + memberPubKeys.emplace_back(members[i]->pdmnState->pubKeyOperator.Get()); } if (!membersSig.VerifySecureAggregated(memberPubKeys, commitmentHash)) { diff --git a/src/llmq/quorums_dkgsession.cpp b/src/llmq/quorums_dkgsession.cpp index 32e3accccabf..036528bcd680 100644 --- a/src/llmq/quorums_dkgsession.cpp +++ b/src/llmq/quorums_dkgsession.cpp @@ -187,7 +187,7 @@ void CDKGSession::SendContributions(CDKGPendingMessages& pendingMessages) skContrib.MakeNewKey(); } - if (!qc.contributions->Encrypt(i, m->dmn->pdmnState->pubKeyOperator, skContrib, PROTOCOL_VERSION)) { + if (!qc.contributions->Encrypt(i, m->dmn->pdmnState->pubKeyOperator.Get(), skContrib, PROTOCOL_VERSION)) { logger.Batch("failed to encrypt contribution for %s", m->dmn->proTxHash.ToString()); return; } @@ -1219,7 +1219,7 @@ std::vector CDKGSession::FinalizeCommitments() fqc.signers[signerIndex] = true; aggSigs.emplace_back(qc.sig); - aggPks.emplace_back(m->dmn->pdmnState->pubKeyOperator); + aggPks.emplace_back(m->dmn->pdmnState->pubKeyOperator.Get()); signerIds.emplace_back(m->id); thresholdSigs.emplace_back(qc.quorumSig); diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index b0de51044a92..629b8bf3c846 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -313,7 +313,7 @@ std::set BatchVerifyMessageSigs(CDKGSession& session, const std::vector< break; } - pubKeys.emplace_back(member->dmn->pdmnState->pubKeyOperator); + pubKeys.emplace_back(member->dmn->pdmnState->pubKeyOperator.Get()); messageHashes.emplace_back(msgHash); } if (!revertToSingleVerification) { @@ -353,7 +353,7 @@ std::set BatchVerifyMessageSigs(CDKGSession& session, const std::vector< const auto& msg = *p.second; auto member = session.GetMember(msg.proTxHash); - bool valid = msg.sig.VerifyInsecure(member->dmn->pdmnState->pubKeyOperator, msg.GetSignHash()); + bool valid = msg.sig.VerifyInsecure(member->dmn->pdmnState->pubKeyOperator.Get(), msg.GetSignHash()); if (!valid) { ret.emplace(p.first); } diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 5ec2710fcc64..cc1c42ee428b 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -769,7 +769,7 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks() continue; } - if (!islock.sig.GetSig().IsValid()) { + if (!islock.sig.Get().IsValid()) { batchVerifier.badSources.emplace(nodeId); continue; } @@ -787,7 +787,7 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks() return false; } uint256 signHash = CLLMQUtils::BuildSignHash(llmqType, quorum->qc.quorumHash, id, islock.txid); - batchVerifier.PushMessage(nodeId, hash, signHash, islock.sig.GetSig(), quorum->qc.quorumPublicKey); + batchVerifier.PushMessage(nodeId, hash, signHash, islock.sig.Get(), quorum->qc.quorumPublicKey); // We can reconstruct the CRecoveredSig objects from the islock and pass it to the signing manager, which // avoids unnecessary double-verification of the signature. We however only do this when verification here diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index 8ae80c60634a..58b0c096fc6f 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -31,8 +31,8 @@ UniValue CRecoveredSig::ToJson() const ret.push_back(Pair("quorumHash", quorumHash.ToString())); ret.push_back(Pair("id", id.ToString())); ret.push_back(Pair("msgHash", msgHash.ToString())); - ret.push_back(Pair("sig", sig.GetSig().ToString())); - ret.push_back(Pair("hash", sig.GetSig().GetHash().ToString())); + ret.push_back(Pair("sig", sig.Get().ToString())); + ret.push_back(Pair("hash", sig.Get().GetHash().ToString())); return ret; } @@ -575,13 +575,13 @@ bool CSigningManager::ProcessPendingRecoveredSigs(CConnman& connman) for (auto& recSig : v) { // we didn't verify the lazy signature until now - if (!recSig.sig.GetSig().IsValid()) { + if (!recSig.sig.Get().IsValid()) { batchVerifier.badSources.emplace(nodeId); break; } const auto& quorum = quorums.at(std::make_pair((Consensus::LLMQType)recSig.llmqType, recSig.quorumHash)); - batchVerifier.PushMessage(nodeId, recSig.GetHash(), CLLMQUtils::BuildSignHash(recSig), recSig.sig.GetSig(), quorum->qc.quorumPublicKey); + batchVerifier.PushMessage(nodeId, recSig.GetHash(), CLLMQUtils::BuildSignHash(recSig), recSig.sig.Get(), quorum->qc.quorumPublicKey); verifyCount++; } } diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index 1e90e27ca714..2c047498acb5 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -589,7 +589,7 @@ bool CSigSharesManager::ProcessPendingSigShares(CConnman& connman) // we didn't check this earlier because we use a lazy BLS signature and tried to avoid doing the expensive // deserialization in the message thread - if (!sigShare.sigShare.GetSig().IsValid()) { + if (!sigShare.sigShare.Get().IsValid()) { BanNode(nodeId); // don't process any additional shares from this node break; @@ -605,7 +605,7 @@ bool CSigSharesManager::ProcessPendingSigShares(CConnman& connman) assert(false); } - batchVerifier.PushMessage(nodeId, sigShare.GetKey(), sigShare.GetSignHash(), sigShare.sigShare.GetSig(), pubKeyShare); + batchVerifier.PushMessage(nodeId, sigShare.GetKey(), sigShare.GetSignHash(), sigShare.sigShare.Get(), pubKeyShare); verifyCount++; } } @@ -735,7 +735,7 @@ void CSigSharesManager::TryRecoverSig(const CQuorumCPtr& quorum, const uint256& idsForRecovery.reserve((size_t) quorum->params.threshold); for (auto it = sigShares->begin(); it != sigShares->end() && sigSharesForRecovery.size() < quorum->params.threshold; ++it) { auto& sigShare = it->second; - sigSharesForRecovery.emplace_back(sigShare.sigShare.GetSig()); + sigSharesForRecovery.emplace_back(sigShare.sigShare.Get()); idsForRecovery.emplace_back(CBLSId::FromHash(quorum->members[sigShare.quorumMember]->proTxHash)); } @@ -762,7 +762,7 @@ void CSigSharesManager::TryRecoverSig(const CQuorumCPtr& quorum, const uint256& rs.quorumHash = quorum->qc.quorumHash; rs.id = id; rs.msgHash = msgHash; - rs.sig.SetSig(recoveredSig); + rs.sig.Set(recoveredSig); rs.UpdateHash(); // There should actually be no need to verify the self-recovered signatures as it should always succeed. Let's @@ -1422,8 +1422,8 @@ void CSigSharesManager::Sign(const CQuorumCPtr& quorum, const uint256& id, const sigShare.quorumMember = (uint16_t)memberIdx; uint256 signHash = CLLMQUtils::BuildSignHash(sigShare); - sigShare.sigShare.SetSig(skShare.Sign(signHash)); - if (!sigShare.sigShare.GetSig().IsValid()) { + sigShare.sigShare.Set(skShare.Sign(signHash)); + if (!sigShare.sigShare.Get().IsValid()) { LogPrintf("CSigSharesManager::%s -- failed to sign sigShare. signHash=%s, id=%s, msgHash=%s, time=%s\n", __func__, signHash.ToString(), sigShare.id.ToString(), sigShare.msgHash.ToString(), t.count()); return; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index db26aae38ac5..4f10ced78d97 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2180,7 +2180,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // we have no idea about (e.g we were offline)? How to handle them? } - if (!dstx.CheckSignature(dmn->pdmnState->pubKeyOperator)) { + if (!dstx.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { LogPrint(BCLog::PRIVATESEND, "DSTX -- CheckSignature() failed for %s\n", hashTx.ToString()); return false; } diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index c892136b3563..0c18806d6cee 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -66,7 +66,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint); if (!dmn) return; - if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) { + if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { LOCK(cs_main); Misbehaving(pfrom->id, 10); return; diff --git a/src/privatesend/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp index 5542a79e7467..12d8c3e41986 100644 --- a/src/privatesend/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -121,7 +121,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm auto dmn = mnList.GetValidMNByCollateral(dsq.masternodeOutpoint); if (!dmn) return; - if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator)) { + if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { LOCK(cs_main); Misbehaving(pfrom->id, 10); return; diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 657b7caedec9..5f1927d4bb46 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -367,14 +367,7 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB static void NotifyMasternodeListChanged(ClientModel *clientmodel, const CDeterministicMNList& newList) { - static int64_t nLastMasternodeUpdateNotification = 0; - int64_t now = GetTimeMillis(); - // if we are in-sync, update the UI regardless of last update time - // no need to refresh masternode list/stats as often as blocks etc. - if (masternodeSync.IsBlockchainSynced() || now - nLastMasternodeUpdateNotification > MODEL_UPDATE_DELAY*4*5) { - clientmodel->setMasternodeList(newList); - nLastMasternodeUpdateNotification = now; - } + clientmodel->setMasternodeList(newList); } static void NotifyAdditionalDataSyncProgressChanged(ClientModel *clientmodel, double nSyncProgress) diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp index 4cc0decd796c..b86a84053a7c 100644 --- a/src/qt/masternodelist.cpp +++ b/src/qt/masternodelist.cpp @@ -35,7 +35,9 @@ MasternodeList::MasternodeList(const PlatformStyle* platformStyle, QWidget* pare clientModel(0), walletModel(0), fFilterUpdatedDIP3(true), - nTimeFilterUpdatedDIP3(0) + nTimeFilterUpdatedDIP3(0), + nTimeUpdatedDIP3(0), + mnListChanged(true) { ui->setupUi(this); @@ -89,7 +91,7 @@ void MasternodeList::setClientModel(ClientModel* model) this->clientModel = model; if (model) { // try to update list when masternode count changes - connect(clientModel, SIGNAL(masternodeListChanged()), this, SLOT(updateDIP3ListForced())); + connect(clientModel, SIGNAL(masternodeListChanged()), this, SLOT(handleMasternodeListChanged())); } } @@ -104,37 +106,48 @@ void MasternodeList::showContextMenuDIP3(const QPoint& point) if (item) contextMenuDIP3->exec(QCursor::pos()); } -void MasternodeList::updateDIP3ListScheduled() +void MasternodeList::handleMasternodeListChanged() { - updateDIP3List(false); + LOCK(cs_dip3list); + mnListChanged = true; } -void MasternodeList::updateDIP3ListForced() +void MasternodeList::updateDIP3ListScheduled() { - updateDIP3List(true); -} + TRY_LOCK(cs_dip3list, fLockAcquired); + if (!fLockAcquired) return; -void MasternodeList::updateDIP3List(bool fForce) -{ if (!clientModel || ShutdownRequested()) { return; } - TRY_LOCK(cs_dip3list, fLockAcquired); - if (!fLockAcquired) return; - // To prevent high cpu usage update only once in MASTERNODELIST_FILTER_COOLDOWN_SECONDS seconds // after filter was last changed unless we want to force the update. - if (!fForce) { - if (!fFilterUpdatedDIP3) return; - + if (fFilterUpdatedDIP3) { int64_t nSecondsToWait = nTimeFilterUpdatedDIP3 - GetTime() + MASTERNODELIST_FILTER_COOLDOWN_SECONDS; ui->countLabelDIP3->setText(QString::fromStdString(strprintf("Please wait... %d", nSecondsToWait))); - if (nSecondsToWait > 0) return; + if (nSecondsToWait <= 0) { + updateDIP3List(); + fFilterUpdatedDIP3 = false; + } + } else if (mnListChanged) { + int64_t nSecondsToWait = nTimeUpdatedDIP3 - GetTime() + MASTERNODELIST_UPDATE_SECONDS; + + if (nSecondsToWait <= 0) { + updateDIP3List(); + mnListChanged = false; + } + } +} + +void MasternodeList::updateDIP3List() +{ + if (!clientModel || ShutdownRequested()) { + return; } - fFilterUpdatedDIP3 = false; + LOCK(cs_dip3list); QString strToFilter; ui->countLabelDIP3->setText("Updating..."); @@ -143,6 +156,8 @@ void MasternodeList::updateDIP3List(bool fForce) ui->tableWidgetMasternodesDIP3->setRowCount(0); auto mnList = clientModel->getMasternodeList(); + nTimeUpdatedDIP3 = GetTime(); + auto projectedPayees = mnList.GetProjectedMNPayees(mnList.GetValidMNsCount()); std::map nextPayments; for (size_t i = 0; i < projectedPayees.size(); i++) { diff --git a/src/qt/masternodelist.h b/src/qt/masternodelist.h index aecfd707f808..e4cff4942a35 100644 --- a/src/qt/masternodelist.h +++ b/src/qt/masternodelist.h @@ -12,7 +12,7 @@ #include #include -#define MASTERNODELIST_UPDATE_SECONDS 15 +#define MASTERNODELIST_UPDATE_SECONDS 3 #define MASTERNODELIST_FILTER_COOLDOWN_SECONDS 3 namespace Ui @@ -42,6 +42,7 @@ class MasternodeList : public QWidget private: QMenu* contextMenuDIP3; int64_t nTimeFilterUpdatedDIP3; + int64_t nTimeUpdatedDIP3; bool fFilterUpdatedDIP3; QTimer* timer; @@ -54,9 +55,11 @@ class MasternodeList : public QWidget QString strCurrentFilterDIP3; + bool mnListChanged; + CDeterministicMNCPtr GetSelectedDIP3MN(); - void updateDIP3List(bool fForce); + void updateDIP3List(); Q_SIGNALS: void doubleClicked(const QModelIndex&); @@ -70,7 +73,7 @@ private Q_SLOTS: void copyProTxHash_clicked(); void copyCollateralOutpoint_clicked(); + void handleMasternodeListChanged(); void updateDIP3ListScheduled(); - void updateDIP3ListForced(); }; #endif // MASTERNODELIST_H diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 24ef9e22b9b2..5efeeb2500fd 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -569,7 +569,7 @@ UniValue masternodelist(const JSONRPCRequest& request) CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString() << " " << CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString() << " " << collateralAddressStr << " " << - dmn->pdmnState->pubKeyOperator.ToString(); + dmn->pdmnState->pubKeyOperator.Get().ToString(); std::string strInfo = streamInfo.str(); if (strFilter !="" && strInfo.find(strFilter) == std::string::npos && strOutpoint.find(strFilter) == std::string::npos) return; @@ -583,7 +583,7 @@ UniValue masternodelist(const JSONRPCRequest& request) objMN.push_back(Pair("owneraddress", CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString())); objMN.push_back(Pair("votingaddress", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString())); objMN.push_back(Pair("collateraladdress", collateralAddressStr)); - objMN.push_back(Pair("pubkeyoperator", dmn->pdmnState->pubKeyOperator.ToString())); + objMN.push_back(Pair("pubkeyoperator", dmn->pdmnState->pubKeyOperator.Get().ToString())); obj.push_back(Pair(strOutpoint, objMN)); } else if (strMode == "lastpaidblock") { if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; @@ -600,7 +600,7 @@ UniValue masternodelist(const JSONRPCRequest& request) obj.push_back(Pair(strOutpoint, CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString())); } else if (strMode == "pubkeyoperator") { if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) return; - obj.push_back(Pair(strOutpoint, dmn->pdmnState->pubKeyOperator.ToString())); + obj.push_back(Pair(strOutpoint, dmn->pdmnState->pubKeyOperator.Get().ToString())); } else if (strMode == "status") { std::string strStatus = dmnToStatus(dmn); if (strFilter !="" && strStatus.find(strFilter) == std::string::npos && diff --git a/src/rpc/rpcevo.cpp b/src/rpc/rpcevo.cpp index 7baf1444e46b..4c5ed8468770 100644 --- a/src/rpc/rpcevo.cpp +++ b/src/rpc/rpcevo.cpp @@ -623,7 +623,7 @@ UniValue protx_update_service(const JSONRPCRequest& request) throw std::runtime_error(strprintf("masternode with proTxHash %s not found", ptx.proTxHash.ToString())); } - if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator) { + if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator.Get()) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("the operator key does not belong to the registered public key")); } @@ -713,7 +713,7 @@ UniValue protx_update_registrar(const JSONRPCRequest& request) if (!dmn) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString())); } - ptx.pubKeyOperator = dmn->pdmnState->pubKeyOperator; + ptx.pubKeyOperator = dmn->pdmnState->pubKeyOperator.Get(); ptx.keyIDVoting = dmn->pdmnState->keyIDVoting; ptx.scriptPayout = dmn->pdmnState->scriptPayout; @@ -808,7 +808,7 @@ UniValue protx_revoke(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("masternode %s not found", ptx.proTxHash.ToString())); } - if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator) { + if (keyOperator.GetPublicKey() != dmn->pdmnState->pubKeyOperator.Get()) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("the operator key does not belong to the registered public key")); } diff --git a/src/test/evo_simplifiedmns_tests.cpp b/src/test/evo_simplifiedmns_tests.cpp index ca1eabd5ee40..a1e2b0875063 100644 --- a/src/test/evo_simplifiedmns_tests.cpp +++ b/src/test/evo_simplifiedmns_tests.cpp @@ -29,7 +29,7 @@ BOOST_AUTO_TEST_CASE(simplifiedmns_merkleroots) CBLSSecretKey sk; sk.SetBuf(skBuf, sizeof(skBuf)); - smle.pubKeyOperator = sk.GetPublicKey(); + smle.pubKeyOperator.Set(sk.GetPublicKey()); smle.keyIDVoting.SetHex(strprintf("%040x", i)); smle.isValid = true; diff --git a/src/txmempool.cpp b/src/txmempool.cpp index a293915bf19a..8a907c468ceb 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -450,7 +450,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(proTx.proTxHash); assert(dmn); newit->validForProTxKey = ::SerializeHash(dmn->pdmnState->pubKeyOperator); - if (dmn->pdmnState->pubKeyOperator != proTx.pubKeyOperator) { + if (dmn->pdmnState->pubKeyOperator.Get() != proTx.pubKeyOperator) { newit->isKeyChangeProTx = true; } } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) { @@ -461,7 +461,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, auto dmn = deterministicMNManager->GetListAtChainTip().GetMN(proTx.proTxHash); assert(dmn); newit->validForProTxKey = ::SerializeHash(dmn->pdmnState->pubKeyOperator); - if (dmn->pdmnState->pubKeyOperator != CBLSPublicKey()) { + if (dmn->pdmnState->pubKeyOperator.Get() != CBLSPublicKey()) { newit->isKeyChangeProTx = true; } } @@ -1285,7 +1285,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { return true; // i.e. failed to find validated ProTx == conflict } // only allow one operator key change in the mempool - if (dmn->pdmnState->pubKeyOperator != proTx.pubKeyOperator) { + if (dmn->pdmnState->pubKeyOperator.Get() != proTx.pubKeyOperator) { if (hasKeyChangeInMempool(proTx.proTxHash)) { return true; } @@ -1307,7 +1307,7 @@ bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const { return true; // i.e. failed to find validated ProTx == conflict } // only allow one operator key change in the mempool - if (dmn->pdmnState->pubKeyOperator != CBLSPublicKey()) { + if (dmn->pdmnState->pubKeyOperator.Get() != CBLSPublicKey()) { if (hasKeyChangeInMempool(proTx.proTxHash)) { return true; } From 4739daddc87d11bf9e68e529893feba2b28845a0 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 13 Jun 2019 12:03:20 +0300 Subject: [PATCH 153/987] Process/keep messages/connections from PoSe-banned MNs (#2967) * Process/keep/count votes from PoSe-banned MNs * Process dstx from PoSe-banned MNs * Recognize PoSe-banned MNs as MNs --- src/evo/deterministicmns.cpp | 11 ++++++++++- src/evo/deterministicmns.h | 1 + src/evo/mnauth.cpp | 2 +- src/governance/governance-object.cpp | 4 ++-- src/governance/governance.cpp | 4 ++-- src/net.cpp | 6 +++--- src/net_processing.cpp | 2 +- 7 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index f5e3fc036801..96bb8086a82e 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -168,11 +168,20 @@ CDeterministicMNCPtr CDeterministicMNList::GetValidMNByCollateral(const COutPoin return dmn; } -CDeterministicMNCPtr CDeterministicMNList::GetValidMNByService(const CService& service) const +CDeterministicMNCPtr CDeterministicMNList::GetMNByService(const CService& service) const { return GetUniquePropertyMN(service); } +CDeterministicMNCPtr CDeterministicMNList::GetValidMNByService(const CService& service) const +{ + auto dmn = GetUniquePropertyMN(service); + if (dmn && !IsMNValid(dmn)) { + return nullptr; + } + return dmn; +} + static int CompareByLastPaid_GetHeight(const CDeterministicMN& dmn) { int height = dmn.pdmnState->nLastPaidHeight; diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 286ef7023b0a..6ddc32a399d7 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -306,6 +306,7 @@ class CDeterministicMNList CDeterministicMNCPtr GetMNByOperatorKey(const CBLSPublicKey& pubKey); CDeterministicMNCPtr GetMNByCollateral(const COutPoint& collateralOutpoint) const; CDeterministicMNCPtr GetValidMNByCollateral(const COutPoint& collateralOutpoint) const; + CDeterministicMNCPtr GetMNByService(const CService& service) const; CDeterministicMNCPtr GetValidMNByService(const CService& service) const; CDeterministicMNCPtr GetMNPayee() const; diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index 5ac3e43807bb..ca735514fdfd 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -72,7 +72,7 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS } auto mnList = deterministicMNManager->GetListAtChainTip(); - auto dmn = mnList.GetValidMN(mnauth.proRegTxHash); + auto dmn = mnList.GetMN(mnauth.proRegTxHash); if (!dmn) { LOCK(cs_main); // in case he was unlucky and not up to date, just let him be connected as a regular node, which gives him diff --git a/src/governance/governance-object.cpp b/src/governance/governance-object.cpp index 63c2793e0840..0cac4f4b9a9a 100644 --- a/src/governance/governance-object.cpp +++ b/src/governance/governance-object.cpp @@ -118,7 +118,7 @@ bool CGovernanceObject::ProcessVote(CNode* pfrom, } auto mnList = deterministicMNManager->GetListAtChainTip(); - auto dmn = mnList.GetValidMNByCollateral(vote.GetMasternodeOutpoint()); + auto dmn = mnList.GetMNByCollateral(vote.GetMasternodeOutpoint()); if (!dmn) { std::ostringstream ostr; @@ -227,7 +227,7 @@ void CGovernanceObject::ClearMasternodeVotes() vote_m_it it = mapCurrentMNVotes.begin(); while (it != mapCurrentMNVotes.end()) { - if (!mnList.HasValidMNByCollateral(it->first)) { + if (!mnList.HasMNByCollateral(it->first)) { fileVotes.RemoveVotesFromMasternode(it->first); mapCurrentMNVotes.erase(it++); } else { diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index 7470f379f9a1..a7c600f64a93 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -474,11 +474,11 @@ std::vector CGovernanceManager::GetCurrentVotes(const uint256& auto mnList = deterministicMNManager->GetListAtChainTip(); std::map mapMasternodes; if (mnCollateralOutpointFilter.IsNull()) { - mnList.ForEachMN(true, [&](const CDeterministicMNCPtr& dmn) { + mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) { mapMasternodes.emplace(dmn->collateralOutpoint, dmn); }); } else { - auto dmn = mnList.GetValidMNByCollateral(mnCollateralOutpointFilter); + auto dmn = mnList.GetMNByCollateral(mnCollateralOutpointFilter); if (dmn) { mapMasternodes.emplace(dmn->collateralOutpoint, dmn); } diff --git a/src/net.cpp b/src/net.cpp index ce125ac95045..a859f1b56dc6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1889,7 +1889,7 @@ void CConnman::ThreadOpenConnections() { CAddrInfo addr = addrman.Select(fFeeler); - bool isMasternode = mnList.GetValidMNByService(addr) != nullptr; + bool isMasternode = mnList.GetMNByService(addr) != nullptr; // if we selected an invalid address, restart if (!addr.IsValid() || setConnected.count(addr.GetGroup())) @@ -2081,7 +2081,7 @@ void CConnman::ThreadOpenMasternodeConnections() std::vector pending; for (const auto& group : masternodeQuorumNodes) { for (const auto& proRegTxHash : group.second) { - auto dmn = mnList.GetValidMN(proRegTxHash); + auto dmn = mnList.GetMN(proRegTxHash); if (!dmn) { continue; } @@ -2792,7 +2792,7 @@ bool CConnman::IsMasternodeQuorumNode(const CNode* pnode) uint256 assumedProTxHash; if (pnode->verifiedProRegTxHash.IsNull() && !pnode->fInbound) { auto mnList = deterministicMNManager->GetListAtChainTip(); - auto dmn = mnList.GetValidMNByService(pnode->addr); + auto dmn = mnList.GetMNByService(pnode->addr); if (dmn == nullptr) { // This is definitely not a masternode return false; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 4f10ced78d97..e154f1ee1f54 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -2167,7 +2167,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return true; // not an error } - auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMNByCollateral(dstx.masternodeOutpoint); + auto dmn = deterministicMNManager->GetListAtChainTip().GetMNByCollateral(dstx.masternodeOutpoint); if(!dmn) { LogPrint(BCLog::PRIVATESEND, "DSTX -- Can't find masternode %s to verify %s\n", dstx.masternodeOutpoint.ToStringShort(), hashTx.ToString()); return false; From bfcfb70d8c60d5b5a186f923a1b7c503257e2a98 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 13 Jun 2019 12:04:07 +0300 Subject: [PATCH 154/987] Ignore blocks that do not match the filter in getmerkleblocks rpc (#2973) Also clarify method description a bit --- src/rpc/blockchain.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 1ded789e017b..7df8fb3f5ab6 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -838,7 +838,7 @@ UniValue getmerkleblocks(const JSONRPCRequest& request) if (request.fHelp || request.params.size() < 1 || request.params.size() > 3) throw std::runtime_error( "getmerkleblocks \"filter\" \"hash\" ( count )\n" - "\nReturns an array of items with information about merkleblocks starting from which match .\n" + "\nReturns an array of hex-encoded merkleblocks for blocks starting from which match .\n" "\nArguments:\n" "1. \"filter\" (string, required) The hex encoded bloom filter\n" "2. \"hash\" (string, required) The block hash\n" @@ -899,16 +899,25 @@ UniValue getmerkleblocks(const JSONRPCRequest& request) for (; pblockindex; pblockindex = chainActive.Next(pblockindex)) { + if (--nCount < 0) { + break; + } + if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) { // this shouldn't happen, we already checked pruning case earlier throw JSONRPCError(RPC_MISC_ERROR, "Block not found on disk"); } + + CMerkleBlock merkleblock(block, filter); + if (merkleblock.vMatchedTxn.empty()) { + // ignore blocks that do not match the filter + continue; + } + CDataStream ssMerkleBlock(SER_NETWORK, PROTOCOL_VERSION); - ssMerkleBlock << CMerkleBlock(block, filter); + ssMerkleBlock << merkleblock; std::string strHex = HexStr(ssMerkleBlock); arrMerkleBlocks.push_back(strHex); - if (--nCount <= 0) - break; } return arrMerkleBlocks; } From d9a4dea613ecff9fb2293dfb59adbae9833a5561 Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 14 Jun 2019 01:25:32 -0500 Subject: [PATCH 155/987] Remove CValidationInterface::UpdatedTransaction This removes another callback from block connection logic, making it easier to reason about the wallet-RPCs-returns-stale-info issue. UpdatedTransaction was previously used by the GUI to display coinbase transactions only after they have a block built on top of them. This worked fine for in most cases, but only worked due to a corner case if the user received a coinbase payout in a block immediately prior to restart. In that case, the normal process of caching the most recent coinbase transaction's hash would not work, and instead it would only work because of the on-load -checkblocks calling DisconnectBlock and ConnectBlock on the current tip. In order to make this more robust, a full mapWallet loop after the first block which is connected after restart was added. --- src/validation.cpp | 5 ----- src/validationinterface.cpp | 3 --- src/validationinterface.h | 3 --- src/wallet/wallet.cpp | 41 ++++++++++++++++++++++++------------- src/wallet/wallet.h | 6 ++++-- 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index efee26789e8c..b3ef4865a29b 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2298,11 +2298,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd int64_t nTime6 = GetTimeMicros(); nTimeIndex += nTime6 - nTime5; LogPrint(BCLog::BENCHMARK, " - Index writing: %.2fms [%.2fs]\n", 0.001 * (nTime6 - nTime5), nTimeIndex * 0.000001); - // Watch for changes to the previous coinbase transaction. - static uint256 hashPrevBestCoinBase; - GetMainSignals().UpdatedTransaction(hashPrevBestCoinBase); - hashPrevBestCoinBase = block.vtx[0]->GetHash(); - evoDb->WriteBestBlock(pindex->GetBlockHash()); int64_t nTime7 = GetTimeMicros(); nTimeCallbacks += nTime7 - nTime6; diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index d666742eb497..e811a2196afd 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -21,7 +21,6 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1, _2)); g_signals.NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1, _2)); g_signals.NotifyChainLock.connect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1, _2)); - g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); @@ -40,7 +39,6 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1)); g_signals.NotifyChainLock.disconnect(boost::bind(&CValidationInterface::NotifyChainLock, pwalletIn, _1, _2)); g_signals.NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1, _2)); g_signals.TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); @@ -62,7 +60,6 @@ void UnregisterAllValidationInterfaces() { g_signals.Broadcast.disconnect_all_slots(); g_signals.Inventory.disconnect_all_slots(); g_signals.SetBestChain.disconnect_all_slots(); - g_signals.UpdatedTransaction.disconnect_all_slots(); g_signals.NotifyTransactionLock.disconnect_all_slots(); g_signals.NotifyChainLock.disconnect_all_slots(); g_signals.TransactionAddedToMempool.disconnect_all_slots(); diff --git a/src/validationinterface.h b/src/validationinterface.h index 0ca3dba23041..8d2df801c1d5 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -53,7 +53,6 @@ class CValidationInterface { virtual void NotifyInstantSendDoubleSpendAttempt(const CTransaction ¤tTx, const CTransaction &previousTx) {} virtual void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) {} virtual void SetBestChain(const CBlockLocator &locator) {} - virtual bool UpdatedTransaction(const uint256 &hash) { return false;} virtual void Inventory(const uint256 &hash) {} virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} @@ -92,8 +91,6 @@ struct CMainSignals { 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. */ boost::signals2::signal SetBestChain; /** Notifies listeners about an inventory item being seen on the network. */ diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c959309da835..c5e918fb30c2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1331,6 +1331,33 @@ void CWallet::BlockConnected(const std::shared_ptr& pblock, const for (size_t i = 0; i < pblock->vtx.size(); i++) { SyncTransaction(pblock->vtx[i], pindex, i); } + + // The GUI expects a NotifyTransactionChanged when a coinbase tx + // which is in our wallet moves from in-the-best-block to + // 2-confirmations (as it only displays them at that time). + // We do that here. + if (hashPrevBestCoinbase.IsNull()) { + // Immediately after restart we have no idea what the coinbase + // transaction from the previous block is. + // For correctness we scan over the entire wallet, looking for + // the previous block's coinbase, just in case it is ours, so + // that we can notify the UI that it should now be displayed. + if (pindex->pprev) { + for (const std::pair& p : mapWallet) { + if (p.second.IsCoinBase() && p.second.hashBlock == pindex->pprev->GetBlockHash()) { + NotifyTransactionChanged(this, p.first, CT_UPDATED); + break; + } + } + } + } else { + std::map::const_iterator mi = mapWallet.find(hashPrevBestCoinbase); + if (mi != mapWallet.end()) { + NotifyTransactionChanged(this, hashPrevBestCoinbase, CT_UPDATED); + } + } + + hashPrevBestCoinbase = pblock->vtx[0]->GetHash(); } void CWallet::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) { @@ -4468,20 +4495,6 @@ void CWallet::GetAllReserveKeys(std::set& setAddress) const } } -bool CWallet::UpdatedTransaction(const uint256 &hashTx) -{ - { - LOCK(cs_wallet); - // Only notify UI if this transaction is in this wallet - std::map::const_iterator mi = mapWallet.find(hashTx); - if (mi != mapWallet.end()){ - NotifyTransactionChanged(this, hashTx, CT_UPDATED); - return true; - } - } - return false; -} - void CWallet::GetScriptForMining(std::shared_ptr &script) { std::shared_ptr rKey = std::make_shared(this); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c5b28541a812..8d1654f41068 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -741,6 +741,10 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::unique_ptr dbw; + // Used to NotifyTransactionChanged of the previous block's coinbase when + // the next block comes in + uint256 hashPrevBestCoinbase; + public: /* * Main wallet lock. @@ -1085,8 +1089,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool DelAddressBook(const CTxDestination& address); - bool UpdatedTransaction(const uint256 &hashTx) override; - void Inventory(const uint256 &hash) override { { From 69b42ce6711c1a9ea35c69d89aaead02ff0336a8 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 13 Apr 2017 12:07:46 +0200 Subject: [PATCH 156/987] Merge #10165: [Wallet] Refactoring by using CInputCoin instead of std::pair c37e32a [Wallet] Prevent CInputCoin to be in a null state (NicolasDorier) f597dcb [Wallet] Simplify code using CInputCoin (NicolasDorier) e78bc45 [Wallet] Decouple CInputCoin from CWalletTx (NicolasDorier) fd44ac1 [Wallet] Rename std::pair to CInputCoin (NicolasDorier) Tree-SHA512: d24361fc514a0566bce1c3953d766dfe4fece79c549cb4db2600695a4ce08e85caa61b7717812618e523a2f2a1669877dad2752ed079e2ed2d27249f9bc8590e fix error, based on 1 0 1 6 5 fix error, based on 1 0 1 6 5 --- src/bench/coin_selection.cpp | 2 +- src/wallet/test/wallet_tests.cpp | 2 +- src/wallet/wallet.cpp | 85 +++++++++++++++----------------- src/wallet/wallet.h | 31 +++++++++++- 4 files changed, 71 insertions(+), 49 deletions(-) diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index e866afe407f7..ec6e7a2c17b2 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -48,7 +48,7 @@ static void CoinSelection(benchmark::State& state) addCoin(1000 * COIN, wallet, vCoins); addCoin(3 * COIN, wallet, vCoins); - std::set > setCoinsRet; + std::set setCoinsRet; CAmount nValueRet; bool success = wallet.SelectCoinsMinConf(1003 * COIN, 1, 6, 0, vCoins, setCoinsRet, nValueRet); assert(success); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index c23614eef740..140d4e3691e6 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -31,7 +31,7 @@ extern UniValue importwallet(const JSONRPCRequest& request); std::vector> wtxn; -typedef std::set > CoinSet; +typedef std::set CoinSet; BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c5e918fb30c2..d240c90f8573 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -76,10 +76,10 @@ const uint256 CMerkleTx::ABANDON_HASH(uint256S("00000000000000000000000000000000 struct CompareValueOnly { - bool operator()(const std::pair >& t1, - const std::pair >& t2) const + bool operator()(const CInputCoin& t1, + const CInputCoin& t2) const { - return t1.first < t2.first; + return t1.txout.nValue < t2.txout.nValue; } }; @@ -2601,7 +2601,7 @@ void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlySafe, const } } -static void ApproximateBestSubset(const std::vector > >& vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, +static void ApproximateBestSubset(const std::vector& vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, std::vector& vfBest, CAmount& nBest, bool fUseInstantSend = false, int iterations = 1000) { std::vector vfIncluded; @@ -2626,7 +2626,7 @@ static void ApproximateBestSubset(const std::vector sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) { + if (fUseInstantSend && nTotal + vValue[i].txout.nValue > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) { continue; } //The solver here uses a randomized algorithm, @@ -2637,7 +2637,7 @@ static void ApproximateBestSubset(const std::vector= nTargetValue) { @@ -2647,7 +2647,7 @@ static void ApproximateBestSubset(const std::vector vCoins, - std::set >& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType, bool fUseInstantSend) const + std::set& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType, bool fUseInstantSend) const { setCoinsRet.clear(); nValueRet = 0; @@ -2694,12 +2694,8 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin } // List of values less than target - std::pair > coinLowestLarger; - coinLowestLarger.first = fUseInstantSend - ? sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN - : std::numeric_limits::max(); - coinLowestLarger.second.first = NULL; - std::vector > > vValue; + boost::optional coinLowestLarger; + std::vector vValue; CAmount nTotalLower = 0; random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); @@ -2741,8 +2737,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin continue; int i = output.i; - CAmount n = pcoin->tx->vout[i].nValue; - if (tryDenom == 0 && CPrivateSend::IsDenominatedAmount(n)) continue; // we don't want denom values on first run + + CInputCoin coin = CInputCoin(pcoin, i); + + if (tryDenom == 0 && CPrivateSend::IsDenominatedAmount(coin.txout.nValue)) continue; // we don't want denom values on first run if (nCoinType == ONLY_DENOMINATED) { // Make sure it's actually anonymized @@ -2751,20 +2749,18 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin if (nRounds < privateSendClient.nPrivateSendRounds) continue; } - std::pair > coin = std::make_pair(n, std::make_pair(pcoin, i)); - - if (n == nTargetValue) + if (coin.txout.nValue == nTargetValue) { - setCoinsRet.insert(coin.second); - nValueRet += coin.first; + setCoinsRet.insert(coin); + nValueRet += coin.txout.nValue; return true; } - else if (n < nTargetValue + nMinChange) + else if (coin.txout.nValue < nTargetValue + nMinChange) { vValue.push_back(coin); - nTotalLower += n; + nTotalLower += coin.txout.nValue; } - else if (n < coinLowestLarger.first) + else if (!coinLowestLarger || coin.txout.nValue < coinLowestLarger->txout.nValue) { coinLowestLarger = coin; } @@ -2774,15 +2770,15 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin { for (unsigned int i = 0; i < vValue.size(); ++i) { - setCoinsRet.insert(vValue[i].second); - nValueRet += vValue[i].first; + setCoinsRet.insert(vValue[i]); + nValueRet += vValue[i].txout.nValue; } return true; } if (nTotalLower < nTargetValue) { - if (coinLowestLarger.second.first == NULL) // there is no input larger than nTargetValue + if (!coinLowestLarger) // there is no input larger than nTargetValue { if (tryDenom == 0) // we didn't look at denom yet, let's do it @@ -2791,8 +2787,8 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin // we looked at everything possible and didn't find anything, no luck return false; } - setCoinsRet.insert(coinLowestLarger.second); - nValueRet += coinLowestLarger.first; + setCoinsRet.insert(coinLowestLarger.get()); + nValueRet += coinLowestLarger->txout.nValue; // There is no change in PS, so we know the fee beforehand, // can see if we exceeded the max fee and thus fail quickly. return nCoinType == ONLY_DENOMINATED ? (nValueRet - nTargetValue <= maxTxFee) : true; @@ -2800,7 +2796,6 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin // nTotalLower > nTargetValue break; - } // Solve subset sum by stochastic approximation @@ -2815,11 +2810,11 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin // If we have a bigger coin and (either the stochastic approximation didn't find a good solution, // or the next bigger coin is closer), return the bigger coin - if (coinLowestLarger.second.first && - ((nBest != nTargetValue && nBest < nTargetValue + nMinChange) || coinLowestLarger.first <= nBest)) + if (coinLowestLarger && + ((nBest != nTargetValue && nBest < nTargetValue + nMinChange) || coinLowestLarger->txout.nValue <= nBest)) { - setCoinsRet.insert(coinLowestLarger.second); - nValueRet += coinLowestLarger.first; + setCoinsRet.insert(coinLowestLarger.get()); + nValueRet += coinLowestLarger->txout.nValue; } else { std::string s = "CWallet::SelectCoinsMinConf best subset: "; @@ -2827,9 +2822,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin { if (vfBest[i]) { - setCoinsRet.insert(vValue[i].second); - nValueRet += vValue[i].first; - s += FormatMoney(vValue[i].first) + " "; + setCoinsRet.insert(vValue[i]); + nValueRet += vValue[i].txout.nValue; + s += FormatMoney(vValue[i].txout.nValue) + " "; } } LogPrint(BCLog::SELECTCOINS, "%s - total %s\n", s, FormatMoney(nBest)); @@ -2840,7 +2835,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin return nCoinType == ONLY_DENOMINATED ? (nValueRet - nTargetValue <= maxTxFee) : true; } -bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType nCoinType, bool fUseInstantSend) const +bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType nCoinType, bool fUseInstantSend) const { // Note: this function should never be used for "always free" tx types like dstx @@ -2861,7 +2856,7 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm if(nRounds < privateSendClient.nPrivateSendRounds) continue; } nValueRet += out.tx->tx->vout[out.i].nValue; - setCoinsRet.insert(std::make_pair(out.tx, out.i)); + setCoinsRet.insert(CInputCoin(out.tx, out.i)); if (!coinControl->fRequireAllInputs && nValueRet >= nTargetValue) { // stop when we added at least one input and enough inputs to have at least nTargetValue funds @@ -2873,7 +2868,7 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm } // calculate value from preset inputs and store them - std::set > setPresetCoins; + std::set setPresetCoins; CAmount nValueFromPresetInputs = 0; std::vector vPresetInputs; @@ -2895,7 +2890,7 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm if (nRounds < privateSendClient.nPrivateSendRounds) continue; } nValueFromPresetInputs += pcoin->tx->vout[outpoint.n].nValue; - setPresetCoins.insert(std::make_pair(pcoin, outpoint.n)); + setPresetCoins.insert(CInputCoin(pcoin, outpoint.n)); } else return false; // TODO: Allow non-wallet inputs } @@ -2903,7 +2898,7 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm // remove preset inputs from vCoins for (std::vector::iterator it = vCoins.begin(); it != vCoins.end() && coinControl && coinControl->HasSelected();) { - if (setPresetCoins.count(std::make_pair(it->tx, it->i))) + if (setPresetCoins.count(CInputCoin(it->tx, it->i))) it = vCoins.erase(it); else ++it; @@ -3435,7 +3430,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT assert(txNew.nLockTime < LOCKTIME_THRESHOLD); { - std::set > setCoins; + std::set setCoins; std::vector vecTxDSInTmp; LOCK2(cs_main, cs_wallet); { @@ -3617,9 +3612,9 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // nLockTime set above actually works. vecTxDSInTmp.clear(); for (const auto& coin : setCoins) { - CTxIn txin = CTxIn(coin.first->GetHash(),coin.second,CScript(), + CTxIn txin = CTxIn(coin.outpoint,CScript(), std::numeric_limits::max()-1); - vecTxDSInTmp.push_back(CTxDSIn(txin, coin.first->tx->vout[coin.second].scriptPubKey)); + vecTxDSInTmp.push_back(CTxDSIn(txin, coin.txout.scriptPubKey)); txNew.vin.push_back(txin); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 8d1654f41068..aee2961a4cb8 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -518,7 +518,34 @@ class CWalletTx : public CMerkleTx }; +class CInputCoin { +public: + CInputCoin(const CWalletTx* walletTx, unsigned int i) + { + if (!walletTx) + throw std::invalid_argument("walletTx should not be null"); + if (i >= walletTx->tx->vout.size()) + throw std::out_of_range("The output index is out of range"); + + outpoint = COutPoint(walletTx->GetHash(), i); + txout = walletTx->tx->vout[i]; + } + + COutPoint outpoint; + CTxOut txout; + bool operator<(const CInputCoin& rhs) const { + return outpoint < rhs.outpoint; + } + + bool operator!=(const CInputCoin& rhs) const { + return outpoint != rhs.outpoint; + } + + bool operator==(const CInputCoin& rhs) const { + return outpoint == rhs.outpoint; + } +}; class COutput { @@ -680,7 +707,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * all coins from coinControl are selected; Never select unconfirmed coins * if they are not ours */ - bool SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = true) const; + bool SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = true) const; CWalletDB *pwalletdbEncryption; @@ -869,7 +896,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * completion the coin set and corresponding actual target value is * assembled */ - bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector vCoins, std::set >& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = false) const; + bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector vCoins, std::set& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = false) const; // Coin selection bool SelectPSInOutPairsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector< std::pair >& vecPSInOutPairsRet); From 34a1e93ca2bfb778bc77b9b09766ef1342d97772 Mon Sep 17 00:00:00 2001 From: Pasta Date: Thu, 30 May 2019 19:51:37 -0500 Subject: [PATCH 157/987] remove UpdatedTransaction calls in instantsend code --- src/instantsend.cpp | 12 +++++------- src/llmq/quorums_instantsend.cpp | 12 +++++------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/instantsend.cpp b/src/instantsend.cpp index ff5bf3d7df47..30ad074b550e 100644 --- a/src/instantsend.cpp +++ b/src/instantsend.cpp @@ -529,13 +529,11 @@ void CInstantSend::UpdateLockedTransaction(const CTxLockCandidate& txLockCandida if (!IsLockedInstantSendTransaction(txHash)) return; // not a locked tx, do not update/notify #ifdef ENABLE_WALLET - if (pwalletMain && pwalletMain->UpdatedTransaction(txHash)) { - // notify an external script once threshold is reached - std::string strCmd = GetArg("-instantsendnotify", ""); - if (!strCmd.empty()) { - boost::replace_all(strCmd, "%s", txHash.GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free - } + // notify an external script once threshold is reached + std::string strCmd = GetArg("-instantsendnotify", ""); + if (!strCmd.empty()) { + boost::replace_all(strCmd, "%s", txHash.GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free } #endif diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 5ec2710fcc64..c837b6fc8864 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -934,13 +934,11 @@ void CInstantSendManager::UpdateWalletTransaction(const CTransactionRef& tx, con return; } - if (pwalletMain->UpdatedTransaction(tx->GetHash())) { - // notify an external script once threshold is reached - std::string strCmd = GetArg("-instantsendnotify", ""); - if (!strCmd.empty()) { - boost::replace_all(strCmd, "%s", tx->GetHash().GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free - } + // notify an external script once threshold is reached + std::string strCmd = GetArg("-instantsendnotify", ""); + if (!strCmd.empty()) { + boost::replace_all(strCmd, "%s", tx->GetHash().GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free } #endif From 1dde64aaa0913bc1663b20064fd9a03081580a4f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 7 Apr 2017 15:37:31 +0200 Subject: [PATCH 158/987] Merge #10155: build: Deduplicate version numbers 9ff7818 doc: Update release process for simplified version bumping (Wladimir J. van der Laan) 08d9aee build: Remove duplicate version information from src/clientversion.h (Wladimir J. van der Laan) 168a703 doc: Make build system insert version in Doxyfile (Wladimir J. van der Laan) b67eb8d doc: Remove version numbers from READMEs (Wladimir J. van der Laan) Tree-SHA512: 531e44282b1c1383a382847a5605177917dfbf78acfaa754d1cbadd2e165c7e34ddbd01790f87615083fac359571708c2551ad24b712aab1f84a2068360c3a17 --- configure.ac | 1 + doc/{Doxyfile => Doxyfile.in} | 2 +- doc/README.md | 4 ++-- doc/README_windows.txt | 4 ++-- doc/release-process.md | 19 +++---------------- src/clientversion.h | 26 +++++--------------------- 6 files changed, 14 insertions(+), 42 deletions(-) rename doc/{Doxyfile => Doxyfile.in} (99%) diff --git a/configure.ac b/configure.ac index 30525e87dd4c..c968be164779 100644 --- a/configure.ac +++ b/configure.ac @@ -1206,6 +1206,7 @@ AC_SUBST(QR_LIBS) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/functional/config.ini]) AC_CONFIG_FILES([test/util/buildenv.py],[chmod +x test/util/buildenv.py]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) +AC_CONFIG_FILES([doc/Doxyfile]) AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py]) AC_CONFIG_LINKS([test/util/bitcoin-util-test.py:test/util/bitcoin-util-test.py]) AC_CONFIG_LINKS([test/util/bctest.py:test/util/bctest.py]) diff --git a/doc/Doxyfile b/doc/Doxyfile.in similarity index 99% rename from doc/Doxyfile rename to doc/Doxyfile.in index 07feaf04a5c2..8d84ca35a953 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile.in @@ -41,7 +41,7 @@ PROJECT_NAME = "Dash Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.14.1.0 +PROJECT_NUMBER = @PACKAGE_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/README.md b/doc/README.md index 8f53f3771777..ef5123054ff2 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,5 +1,5 @@ -Dash Core 0.14.1 -===================== +Dash Core +========== This is the official reference wallet for Dash digital currency and comprises the backbone of the Dash peer-to-peer network. You can [download Dash Core](https://www.dash.org/downloads/) or [build it yourself](#building) using the guides below. diff --git a/doc/README_windows.txt b/doc/README_windows.txt index d3bcc8cd22cc..f02c9147fd33 100644 --- a/doc/README_windows.txt +++ b/doc/README_windows.txt @@ -1,5 +1,5 @@ -Dash Core 0.14.1 -===================== +Dash Core +========== Intro ----- diff --git a/doc/release-process.md b/doc/release-process.md index b6ab2b2e1e09..ca02624ca277 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -8,7 +8,7 @@ Release Process Before every minor and major release: * Update [bips.md](bips.md) to account for changes since the last release. -* Update version in sources (see below) +* Update version in `configure.ac` (don't forget to set `CLIENT_VERSION_IS_RELEASE` to `true`) * Write release notes (see below) * Update `src/chainparams.cpp` nMinimumChainWork with information from the getblockchaininfo rpc. * Update `src/chainparams.cpp` defaultAssumeValid with information from the getblockhash rpc. @@ -22,6 +22,7 @@ Before every major release: * Update hardcoded [seeds](/contrib/seeds/README.md). TODO: Give example PR for Dash * Update [`BLOCK_CHAIN_SIZE`](/src/qt/intro.cpp) to the current size plus some overhead. * Update `src/chainparams.cpp` chainTxData with statistics about the transaction count and rate. +* Update version of `contrib/gitian-descriptors/*.yml`: usually one'd want to do this on master after branching off the release - but be sure to at least do it before a new major release ### First time / New builders @@ -35,21 +36,7 @@ Check out the source code in the following directory hierarchy. git clone https://github.com/devrandom/gitian-builder.git git clone https://github.com/dashpay/dash.git -### Dash Core maintainers/release engineers, update (commit) version in sources - -- `configure.ac`: - - `_CLIENT_VERSION_MAJOR` - - `_CLIENT_VERSION_MINOR` - - `_CLIENT_VERSION_REVISION` - - Don't forget to set `_CLIENT_VERSION_IS_RELEASE` to `true` -- `src/clientversion.h`: (this mirrors `configure.ac` - see issue #3539) - - `CLIENT_VERSION_MAJOR` - - `CLIENT_VERSION_MINOR` - - `CLIENT_VERSION_REVISION` - - Don't forget to set `CLIENT_VERSION_IS_RELEASE` to `true` -- `doc/README.md` and `doc/README_windows.txt` -- `doc/Doxyfile`: `PROJECT_NUMBER` contains the full version -- `contrib/gitian-descriptors/*.yml`: usually one'd want to do this on master after branching off the release - but be sure to at least do it before a new major release +### Dash Core maintainers/release engineers, suggestion for writing release notes Write release notes. git shortlog helps a lot, for example: diff --git a/src/clientversion.h b/src/clientversion.h index aad78fb70e51..259849464b39 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -7,29 +7,13 @@ #if defined(HAVE_CONFIG_H) #include "config/dash-config.h" -#else - -/** - * client versioning and copyright year - */ - -//! These need to be macros, as clientversion.cpp's and dash*-res.rc's voodoo requires it -#define CLIENT_VERSION_MAJOR 0 -#define CLIENT_VERSION_MINOR 14 -#define CLIENT_VERSION_REVISION 1 -#define CLIENT_VERSION_BUILD 0 - -//! Set to true for release, false for prerelease or test build -#define CLIENT_VERSION_IS_RELEASE false - -/** - * Copyright year (2009-this) - * Todo: update this when changing our copyright comments in the source - */ -#define COPYRIGHT_YEAR 2018 - #endif //HAVE_CONFIG_H +// Check that required client information is defined +#if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_REVISION) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR) +#error Client version information missing: wasn't defined by dash-config.h nor defined any other way +#endif + /** * Converts the parameter X to a string after macro replacement on X has been performed. * Don't merge these into one macro! From 46db8eb68529030ea7d2af1032a4f6befe5b0b54 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 10 Apr 2017 08:38:39 +0200 Subject: [PATCH 159/987] Merge #10168: Fix build warning from #error text dd7e43e Fix build warning from #error text (John Newbery) Tree-SHA512: a806181ec05ad599c45bd455900d6ad569c601e5cc495d16ec0db538edef4523a5229d1c84d310bb877b1bb81b8a8fc15a3a73da78688109042f18a57db5bd70 --- src/clientversion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clientversion.h b/src/clientversion.h index 259849464b39..6f969f840d77 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -11,7 +11,7 @@ // Check that required client information is defined #if !defined(CLIENT_VERSION_MAJOR) || !defined(CLIENT_VERSION_MINOR) || !defined(CLIENT_VERSION_REVISION) || !defined(CLIENT_VERSION_BUILD) || !defined(CLIENT_VERSION_IS_RELEASE) || !defined(COPYRIGHT_YEAR) -#error Client version information missing: wasn't defined by dash-config.h nor defined any other way +#error Client version information missing: version is not defined by dash-config.h or in any other way #endif /** From b76b91d8216621439fbd8462e89c15f8e792290a Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 17 Apr 2017 22:15:12 +0200 Subject: [PATCH 160/987] Merge #10197: [tests] Functional test warnings 08e51c1 [tests] Remove cache directory by default when running test_runner (John Newbery) c85b080 [test] add warnings to test_runner (John Newbery) Tree-SHA512: 537a8a258e410102708d1e02893f3f45abe7a3a3290536249381a7dc55d74ca78322804bf34178dec1461ec1c29d8f8358c5901ddd1633f8b301b95bcbb6ce6d --- test/functional/test_runner.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 31eca769719b..0e0d07ced890 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -159,6 +159,7 @@ def main(): parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).') parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit') parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.') + parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.') args, unknown_args = parser.parse_known_args() # Create a set to store arguments and create the passon string @@ -218,9 +219,24 @@ def main(): check_script_list(config["environment"]["SRCDIR"]) + if not args.keepcache: + shutil.rmtree("%s/test/cache" % config["environment"]["BUILDDIR"], ignore_errors=True) + run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args) def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=False, args=[]): + # Warn if dashd is already running (unix only) + try: + if subprocess.check_output(["pidof", "dashd"]) is not None: + print("%sWARNING!%s There is already a dashd process running on this system. Tests may fail unexpectedly due to resource contention!" % (BOLD[1], BOLD[0])) + except (OSError, subprocess.SubprocessError): + pass + + # Warn if there is a cache directory + cache_dir = "%s/test/cache" % build_dir + if os.path.isdir(cache_dir): + print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir)) + BOLD = ("","") if os.name == 'posix': # primitive formatting on supported @@ -234,7 +250,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal tests_dir = src_dir + '/test/functional/' flags = ["--srcdir={}/src".format(build_dir)] + args - flags.append("--cachedir=%s/test/cache" % build_dir) + flags.append("--cachedir=%s" % cache_dir) if enable_coverage: coverage = RPCCoverage() @@ -346,9 +362,10 @@ def check_script_list(src_dir): python_files = set([t for t in os.listdir(script_dir) if t[-3:] == ".py"]) missed_tests = list(python_files - set(map(lambda x: x.split()[0], ALL_SCRIPTS + NON_SCRIPTS))) if len(missed_tests) != 0: - print("The following scripts are not being run:" + str(missed_tests)) - print("Check the test lists in test_runner.py") - sys.exit(1) + print("%sWARNING!%s The following scripts are not being run: %s. Check the test lists in test_runner.py." % (BOLD[1], BOLD[0], str(missed_tests))) + if os.getenv('TRAVIS') == 'true': + # On travis this warning is an error to prevent merging incomplete commits into master + sys.exit(1) class RPCCoverage(object): """ From 198558a362107e758182611461d92c9b0a1d7f03 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 24 Apr 2017 14:02:12 +0200 Subject: [PATCH 161/987] Merge #9792: FastRandomContext improvements and switch to ChaCha20 4fd2d2f Add a FastRandomContext::randrange and use it (Pieter Wuille) 1632922 Switch FastRandomContext to ChaCha20 (Pieter Wuille) e04326f Add ChaCha20 (Pieter Wuille) 663fbae FastRandom benchmark (Pieter Wuille) c21cbe6 Introduce FastRandomContext::randbool() (Pieter Wuille) Tree-SHA512: 7fff61e3f6d6dc6ac846ca643d877b377db609646dd401a0e8f50b052c6b9bcd2f5fc34de6bbf28f04afd1724f6279ee163ead5f37d724fb782a00239f35db1d --- configure.ac | 2 + src/Makefile.am | 2 + src/Makefile.test.include | 2 +- src/addrman.cpp | 8 +- src/addrman.h | 11 ++- src/bench/checkqueue.cpp | 2 +- src/bench/crypto_hash.cpp | 25 +++++ src/crypto/chacha20.cpp | 180 +++++++++++++++++++++++++++++++++++ src/crypto/chacha20.h | 26 +++++ src/crypto/common.h | 21 ++++ src/net.h | 2 +- src/random.cpp | 33 ++++--- src/random.h | 78 +++++++++++++-- src/test/addrman_tests.cpp | 9 +- src/test/crypto_tests.cpp | 68 +++++++++++++ src/test/prevector_tests.cpp | 8 +- src/test/random_tests.cpp | 36 ++++++- src/test/test_dash.cpp | 3 +- src/test/test_random.h | 8 +- src/wallet/wallet.cpp | 2 +- 20 files changed, 482 insertions(+), 44 deletions(-) create mode 100644 src/crypto/chacha20.cpp create mode 100644 src/crypto/chacha20.h diff --git a/configure.ac b/configure.ac index c968be164779..3e6682ceb30a 100644 --- a/configure.ac +++ b/configure.ac @@ -594,6 +594,8 @@ AC_CHECK_DECLS([bswap_16, bswap_32, bswap_64],,, #include #endif]) +AC_CHECK_DECLS([__builtin_clz, __builtin_clzl, __builtin_clzll]) + dnl Check for MSG_NOSIGNAL AC_MSG_CHECKING(for MSG_NOSIGNAL) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], diff --git a/src/Makefile.am b/src/Makefile.am index eb5d42fdc0d6..c374d6f03eb3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -374,6 +374,8 @@ crypto_libdash_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) $(PIC_FLAGS) crypto_libdash_crypto_a_SOURCES = \ crypto/aes.cpp \ crypto/aes.h \ + crypto/chacha20.h \ + crypto/chacha20.cpp \ crypto/common.h \ crypto/hmac_sha256.cpp \ crypto/hmac_sha256.h \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 75ec2f683198..1424a3fce507 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -67,8 +67,8 @@ BITCOIN_TESTS =\ test/policyestimator_tests.cpp \ test/pow_tests.cpp \ test/prevector_tests.cpp \ - test/random_tests.cpp \ test/raii_event_tests.cpp \ + test/random_tests.cpp \ test/ratecheck_tests.cpp \ test/reverselock_tests.cpp \ test/rpc_tests.cpp \ diff --git a/src/addrman.cpp b/src/addrman.cpp index 48b8dabd311a..e8bf87a1c6e2 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -366,8 +366,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT); int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvTried[nKBucket][nKBucketPos] == -1) { - nKBucket = (nKBucket + insecure_rand.rand32()) % ADDRMAN_TRIED_BUCKET_COUNT; - nKBucketPos = (nKBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; + nKBucket = (nKBucket + insecure_rand.randbits(ADDRMAN_TRIED_BUCKET_COUNT_LOG2)) % ADDRMAN_TRIED_BUCKET_COUNT; + nKBucketPos = (nKBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE; } int nId = vvTried[nKBucket][nKBucketPos]; assert(mapInfo.count(nId) == 1); @@ -383,8 +383,8 @@ CAddrInfo CAddrMan::Select_(bool newOnly) int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT); int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE); while (vvNew[nUBucket][nUBucketPos] == -1) { - nUBucket = (nUBucket + insecure_rand.rand32()) % ADDRMAN_NEW_BUCKET_COUNT; - nUBucketPos = (nUBucketPos + insecure_rand.rand32()) % ADDRMAN_BUCKET_SIZE; + nUBucket = (nUBucket + insecure_rand.randbits(ADDRMAN_NEW_BUCKET_COUNT_LOG2)) % ADDRMAN_NEW_BUCKET_COUNT; + nUBucketPos = (nUBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE; } int nId = vvNew[nUBucket][nUBucketPos]; assert(mapInfo.count(nId) == 1); diff --git a/src/addrman.h b/src/addrman.h index 413bf45277b5..49f0697ca754 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -136,13 +136,13 @@ class CAddrInfo : public CAddress */ //! total number of buckets for tried addresses -#define ADDRMAN_TRIED_BUCKET_COUNT 256 +#define ADDRMAN_TRIED_BUCKET_COUNT_LOG2 8 //! total number of buckets for new addresses -#define ADDRMAN_NEW_BUCKET_COUNT 1024 +#define ADDRMAN_NEW_BUCKET_COUNT_LOG2 10 //! maximum allowed number of entries in buckets for new and tried addresses -#define ADDRMAN_BUCKET_SIZE 64 +#define ADDRMAN_BUCKET_SIZE_LOG2 6 //! over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8 @@ -171,6 +171,11 @@ class CAddrInfo : public CAddress //! the maximum number of nodes to return in a getaddr call #define ADDRMAN_GETADDR_MAX 2500 +//! Convenience +#define ADDRMAN_TRIED_BUCKET_COUNT (1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2) +#define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2) +#define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2) + /** * Stochastical (IP) address manager */ diff --git a/src/bench/checkqueue.cpp b/src/bench/checkqueue.cpp index 6fa9fe4fe8c4..88a2a570f93d 100644 --- a/src/bench/checkqueue.cpp +++ b/src/bench/checkqueue.cpp @@ -68,7 +68,7 @@ static void CCheckQueueSpeedPrevectorJob(benchmark::State& state) PrevectorJob(){ } PrevectorJob(FastRandomContext& insecure_rand){ - p.resize(insecure_rand.rand32() % (PREVECTOR_SIZE*2)); + p.resize(insecure_rand.randrange(PREVECTOR_SIZE*2)); } bool operator()() { diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index d8af66fd3ff4..27dbbf62b490 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -8,6 +8,7 @@ #include "bench.h" #include "bloom.h" #include "hash.h" +#include "random.h" #include "uint256.h" #include "utiltime.h" #include "crypto/ripemd160.h" @@ -88,6 +89,28 @@ static void HASH_SipHash_0032b(benchmark::State& state) } } +static void FastRandom_32bit(benchmark::State& state) +{ + FastRandomContext rng(true); + uint32_t x; + while (state.KeepRunning()) { + for (int i = 0; i < 1000000; i++) { + x += rng.rand32(); + } + } +} + +static void FastRandom_1bit(benchmark::State& state) +{ + FastRandomContext rng(true); + uint32_t x; + while (state.KeepRunning()) { + for (int i = 0; i < 1000000; i++) { + x += rng.randbool(); + } + } +} + static void HASH_DSHA256_0032b_single(benchmark::State& state) { std::vector in(32,0); @@ -209,3 +232,5 @@ BENCHMARK(HASH_X11_0128b_single); BENCHMARK(HASH_X11_0512b_single); BENCHMARK(HASH_X11_1024b_single); BENCHMARK(HASH_X11_2048b_single); +BENCHMARK(FastRandom_32bit); +BENCHMARK(FastRandom_1bit); diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp new file mode 100644 index 000000000000..816ae870e138 --- /dev/null +++ b/src/crypto/chacha20.cpp @@ -0,0 +1,180 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// Based on the public domain implementation 'merged' by D. J. Bernstein +// See https://cr.yp.to/chacha.html. + +#include "crypto/common.h" +#include "crypto/chacha20.h" + +#include + +constexpr static inline uint32_t rotl32(uint32_t v, int c) { return (v << c) | (v >> (32 - c)); } + +#define QUARTERROUND(a,b,c,d) \ + a += b; d = rotl32(d ^ a, 16); \ + c += d; b = rotl32(b ^ c, 12); \ + a += b; d = rotl32(d ^ a, 8); \ + c += d; b = rotl32(b ^ c, 7); + +static const unsigned char sigma[] = "expand 32-byte k"; +static const unsigned char tau[] = "expand 16-byte k"; + +void ChaCha20::SetKey(const unsigned char* k, size_t keylen) +{ + const unsigned char *constants; + + input[4] = ReadLE32(k + 0); + input[5] = ReadLE32(k + 4); + input[6] = ReadLE32(k + 8); + input[7] = ReadLE32(k + 12); + if (keylen == 32) { /* recommended */ + k += 16; + constants = sigma; + } else { /* keylen == 16 */ + constants = tau; + } + input[8] = ReadLE32(k + 0); + input[9] = ReadLE32(k + 4); + input[10] = ReadLE32(k + 8); + input[11] = ReadLE32(k + 12); + input[0] = ReadLE32(constants + 0); + input[1] = ReadLE32(constants + 4); + input[2] = ReadLE32(constants + 8); + input[3] = ReadLE32(constants + 12); + input[12] = 0; + input[13] = 0; + input[14] = 0; + input[15] = 0; +} + +ChaCha20::ChaCha20() +{ + memset(input, 0, sizeof(input)); +} + +ChaCha20::ChaCha20(const unsigned char* k, size_t keylen) +{ + SetKey(k, keylen); +} + +void ChaCha20::SetIV(uint64_t iv) +{ + input[14] = iv; + input[15] = iv >> 32; +} + +void ChaCha20::Seek(uint64_t pos) +{ + input[12] = pos; + input[13] = pos >> 32; +} + +void ChaCha20::Output(unsigned char* c, size_t bytes) +{ + uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; + uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; + unsigned char *ctarget = NULL; + unsigned char tmp[64]; + unsigned int i; + + if (!bytes) return; + + j0 = input[0]; + j1 = input[1]; + j2 = input[2]; + j3 = input[3]; + j4 = input[4]; + j5 = input[5]; + j6 = input[6]; + j7 = input[7]; + j8 = input[8]; + j9 = input[9]; + j10 = input[10]; + j11 = input[11]; + j12 = input[12]; + j13 = input[13]; + j14 = input[14]; + j15 = input[15]; + + for (;;) { + if (bytes < 64) { + ctarget = c; + c = tmp; + } + x0 = j0; + x1 = j1; + x2 = j2; + x3 = j3; + x4 = j4; + x5 = j5; + x6 = j6; + x7 = j7; + x8 = j8; + x9 = j9; + x10 = j10; + x11 = j11; + x12 = j12; + x13 = j13; + x14 = j14; + x15 = j15; + for (i = 20;i > 0;i -= 2) { + QUARTERROUND( x0, x4, x8,x12) + QUARTERROUND( x1, x5, x9,x13) + QUARTERROUND( x2, x6,x10,x14) + QUARTERROUND( x3, x7,x11,x15) + QUARTERROUND( x0, x5,x10,x15) + QUARTERROUND( x1, x6,x11,x12) + QUARTERROUND( x2, x7, x8,x13) + QUARTERROUND( x3, x4, x9,x14) + } + x0 += j0; + x1 += j1; + x2 += j2; + x3 += j3; + x4 += j4; + x5 += j5; + x6 += j6; + x7 += j7; + x8 += j8; + x9 += j9; + x10 += j10; + x11 += j11; + x12 += j12; + x13 += j13; + x14 += j14; + x15 += j15; + + ++j12; + if (!j12) ++j13; + + WriteLE32(c + 0, x0); + WriteLE32(c + 4, x1); + WriteLE32(c + 8, x2); + WriteLE32(c + 12, x3); + WriteLE32(c + 16, x4); + WriteLE32(c + 20, x5); + WriteLE32(c + 24, x6); + WriteLE32(c + 28, x7); + WriteLE32(c + 32, x8); + WriteLE32(c + 36, x9); + WriteLE32(c + 40, x10); + WriteLE32(c + 44, x11); + WriteLE32(c + 48, x12); + WriteLE32(c + 52, x13); + WriteLE32(c + 56, x14); + WriteLE32(c + 60, x15); + + if (bytes <= 64) { + if (bytes < 64) { + for (i = 0;i < bytes;++i) ctarget[i] = c[i]; + } + input[12] = j12; + input[13] = j13; + return; + } + bytes -= 64; + c += 64; + } +} diff --git a/src/crypto/chacha20.h b/src/crypto/chacha20.h new file mode 100644 index 000000000000..a305977bcd5f --- /dev/null +++ b/src/crypto/chacha20.h @@ -0,0 +1,26 @@ +// Copyright (c) 2017 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_CRYPTO_CHACHA20_H +#define BITCOIN_CRYPTO_CHACHA20_H + +#include +#include + +/** A PRNG class for ChaCha20. */ +class ChaCha20 +{ +private: + uint32_t input[16]; + +public: + ChaCha20(); + ChaCha20(const unsigned char* key, size_t keylen); + void SetKey(const unsigned char* key, size_t keylen); + void SetIV(uint64_t iv); + void Seek(uint64_t pos); + void Output(unsigned char* output, size_t bytes); +}; + +#endif // BITCOIN_CRYPTO_CHACHA20_H diff --git a/src/crypto/common.h b/src/crypto/common.h index 02333fa7d888..e4443a5b286a 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -79,4 +79,25 @@ void static inline WriteBE64(unsigned char* ptr, uint64_t x) memcpy(ptr, (char*)&v, 8); } +/** Return the smallest number n such that (x >> n) == 0 (or 64 if the highest bit in x is set. */ +uint64_t static inline CountBits(uint64_t x) +{ +#ifdef HAVE_DECL___BUILTIN_CLZL + if (sizeof(unsigned long) >= sizeof(uint64_t)) { + return x ? 8 * sizeof(unsigned long) - __builtin_clzl(x) : 0; + } +#endif +#ifdef HAVE_DECL___BUILTIN_CLZLL + if (sizeof(unsigned long long) >= sizeof(uint64_t)) { + return x ? 8 * sizeof(unsigned long long) - __builtin_clzll(x) : 0; + } +#endif + int ret = 0; + while (x) { + x >>= 1; + ++ret; + } + return ret; +} + #endif // BITCOIN_CRYPTO_COMMON_H diff --git a/src/net.h b/src/net.h index 8d2904990427..624ac433250b 100644 --- a/src/net.h +++ b/src/net.h @@ -930,7 +930,7 @@ class CNode // after addresses were pushed. if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey())) { if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { - vAddrToSend[insecure_rand.rand32() % vAddrToSend.size()] = _addr; + vAddrToSend[insecure_rand.randrange(vAddrToSend.size())] = _addr; } else { vAddrToSend.push_back(_addr); } diff --git a/src/random.cpp b/src/random.cpp index 5d1a4c564d4b..b53d5970f679 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -251,22 +251,16 @@ bool GetRandBool(double rate) return r <= v * rate; } -FastRandomContext::FastRandomContext(bool fDeterministic) +void FastRandomContext::RandomSeed() { - // The seed values have some unlikely fixed points which we avoid. - if (fDeterministic) { - Rz = Rw = 11; - } else { - uint32_t tmp; - do { - GetRandBytes((unsigned char*)&tmp, 4); - } while (tmp == 0 || tmp == 0x9068ffffU); - Rz = tmp; - do { - GetRandBytes((unsigned char*)&tmp, 4); - } while (tmp == 0 || tmp == 0x464fffffU); - Rw = tmp; - } + uint256 seed = GetRandHash(); + rng.SetKey(seed.begin(), 32); + requires_seed = false; +} + +FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0) +{ + rng.SetKey(seed.begin(), 32); } bool Random_SanityCheck() @@ -299,3 +293,12 @@ bool Random_SanityCheck() } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ } + +FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0) +{ + if (!fDeterministic) { + return; + } + uint256 seed; + rng.SetKey(seed.begin(), 32); +} diff --git a/src/random.h b/src/random.h index 888ca35b001c..392d5407f496 100644 --- a/src/random.h +++ b/src/random.h @@ -6,6 +6,8 @@ #ifndef BITCOIN_RANDOM_H #define BITCOIN_RANDOM_H +#include "crypto/chacha20.h" +#include "crypto/common.h" #include "uint256.h" #include @@ -35,13 +37,72 @@ void GetStrongRandBytes(unsigned char* buf, int num); * This class is not thread-safe. */ class FastRandomContext { +private: + bool requires_seed; + ChaCha20 rng; + + unsigned char bytebuf[64]; + int bytebuf_size; + + uint64_t bitbuf; + int bitbuf_size; + + void RandomSeed(); + + void FillByteBuffer() + { + if (requires_seed) { + RandomSeed(); + } + rng.Output(bytebuf, sizeof(bytebuf)); + bytebuf_size = sizeof(bytebuf); + } + + void FillBitBuffer() + { + bitbuf = rand64(); + bitbuf_size = 64; + } + public: - explicit FastRandomContext(bool fDeterministic=false); + explicit FastRandomContext(bool fDeterministic = false); + + /** Initialize with explicit seed (only for testing) */ + explicit FastRandomContext(const uint256& seed); + + /** Generate a random 64-bit integer. */ + uint64_t rand64() + { + if (bytebuf_size < 8) FillByteBuffer(); + uint64_t ret = ReadLE64(bytebuf + 64 - bytebuf_size); + bytebuf_size -= 8; + return ret; + } - uint32_t rand32() { - Rz = 36969 * (Rz & 65535) + (Rz >> 16); - Rw = 18000 * (Rw & 65535) + (Rw >> 16); - return (Rw << 16) + Rz; + /** Generate a random (bits)-bit integer. */ + uint64_t randbits(int bits) { + if (bits == 0) { + return 0; + } else if (bits > 32) { + return rand64() >> (64 - bits); + } else { + if (bitbuf_size < bits) FillBitBuffer(); + uint64_t ret = bitbuf & (~(uint64_t)0 >> (64 - bits)); + bitbuf >>= bits; + bitbuf_size -= bits; + return ret; + } + } + + /** Generate a random integer in the range [0..range). */ + uint64_t randrange(uint64_t range) + { + --range; + int bits = CountBits(range); + while (true) { + uint64_t ret = randbits(bits); + if (ret <= range) return ret; + } } uint32_t rand32(uint32_t nMax) { @@ -52,8 +113,11 @@ class FastRandomContext { return rand32(nMax); } - uint32_t Rz; - uint32_t Rw; + /** Generate a random 32-bit integer. */ + uint32_t rand32() { return randbits(32); } + + /** Generate a random boolean. */ + bool randbool() { return randbits(1); } }; /* Number of random bytes returned by GetOSRand. diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 51effc24832e..48d81d8a67b2 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -203,10 +203,11 @@ BOOST_AUTO_TEST_CASE(addrman_select) BOOST_CHECK(addrman.size() == 7); // Test 12: Select pulls from new and tried regardless of port number. - BOOST_CHECK(addrman.Select().ToString() == "250.4.6.6:8333"); - BOOST_CHECK(addrman.Select().ToString() == "250.3.2.2:9999"); - BOOST_CHECK(addrman.Select().ToString() == "250.3.3.3:9999"); - BOOST_CHECK(addrman.Select().ToString() == "250.4.4.4:8333"); + std::set ports; + for (int i = 0; i < 20; ++i) { + ports.insert(addrman.Select().GetPort()); + } + BOOST_CHECK_EQUAL(ports.size(), 3); } BOOST_AUTO_TEST_CASE(addrman_new_collisions) diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 36d57381489e..5a76d781e90c 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -3,12 +3,14 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "crypto/aes.h" +#include "crypto/chacha20.h" #include "crypto/ripemd160.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "crypto/sha512.h" #include "crypto/hmac_sha256.h" #include "crypto/hmac_sha512.h" +#include "random.h" #include "utilstrencodings.h" #include "test/test_dash.h" #include "test/test_random.h" @@ -187,6 +189,19 @@ void TestAES256CBC(const std::string &hexkey, const std::string &hexiv, bool pad } } +void TestChaCha20(const std::string &hexkey, uint64_t nonce, uint64_t seek, const std::string& hexout) +{ + std::vector key = ParseHex(hexkey); + ChaCha20 rng(key.data(), key.size()); + rng.SetIV(nonce); + rng.Seek(seek); + std::vector out = ParseHex(hexout); + std::vector outres; + outres.resize(out.size()); + rng.Output(outres.data(), outres.size()); + BOOST_CHECK(out == outres); +} + std::string LongTestString(void) { std::string ret; for (int i=0; i<200000; i++) { @@ -462,4 +477,57 @@ BOOST_AUTO_TEST_CASE(pbkdf2_hmac_sha512_test) { BOOST_CHECK(HexStr(k, k + 64) == "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8"); } + +BOOST_AUTO_TEST_CASE(chacha20_testvector) +{ + // Test vector from RFC 7539 + TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x4a000000UL, 1, + "224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cb" + "a40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a" + "832c89c167eacd901d7e2bf363"); + + // Test vectors from https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7 + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0, 0, + "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b" + "8f41518a11cc387b669b2ee6586"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000001", 0, 0, + "4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d79" + "2b1c43fea817e9ad275ae546963"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 0x0100000000000000ULL, 0, + "de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b52770" + "62eb7a0433e445f41e3"); + TestChaCha20("0000000000000000000000000000000000000000000000000000000000000000", 1, 0, + "ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc4" + "97a0b466e7d6bbdb0041b2f586b"); + TestChaCha20("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", 0x0706050403020100ULL, 0, + "f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3b" + "e59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc1" + "18be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5" + "a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5" + "360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78" + "fab78c9"); +} + +BOOST_AUTO_TEST_CASE(countbits_tests) +{ + FastRandomContext ctx; + for (int i = 0; i <= 64; ++i) { + if (i == 0) { + // Check handling of zero. + BOOST_CHECK_EQUAL(CountBits(0), 0); + } else if (i < 10) { + for (uint64_t j = 1 << (i - 1); (j >> i) == 0; ++j) { + // Exhaustively test up to 10 bits + BOOST_CHECK_EQUAL(CountBits(j), i); + } + } else { + for (int k = 0; k < 1000; k++) { + // Randomly test 1000 samples of each length above 10 bits. + uint64_t j = ((uint64_t)1) << (i - 1) | ctx.randbits(i - 1); + BOOST_CHECK_EQUAL(CountBits(j), i); + } + } + } +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index f3740c1d64b3..a5886a0d8d96 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -28,6 +28,7 @@ class prevector_tester { typedef typename pretype::size_type Size; bool passed = true; FastRandomContext rand_cache; + uint256 rand_seed; template @@ -183,13 +184,12 @@ class prevector_tester { } ~prevector_tester() { - BOOST_CHECK_MESSAGE(passed, "insecure_rand_Rz: " - << rand_cache.Rz - << ", insecure_rand_Rw: " - << rand_cache.Rw); + BOOST_CHECK_MESSAGE(passed, "insecure_rand: " + rand_seed.ToString()); } + prevector_tester() { seed_insecure_rand(); + rand_seed = insecure_rand_seed; rand_cache = insecure_rand_ctx; } }; diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index c7f84cc37176..2c8abc33f595 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -15,5 +15,39 @@ BOOST_AUTO_TEST_CASE(osrandom_tests) BOOST_CHECK(Random_SanityCheck()); } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_CASE(fastrandom_tests) +{ + // Check that deterministic FastRandomContexts are deterministic + FastRandomContext ctx1(true); + FastRandomContext ctx2(true); + + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); + BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7)); + BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); + BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + + // Check that a nondeterministic ones are not + FastRandomContext ctx3; + FastRandomContext ctx4; + BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal +} +BOOST_AUTO_TEST_CASE(fastrandom_randbits) +{ + FastRandomContext ctx1; + FastRandomContext ctx2; + for (int bits = 0; bits < 63; ++bits) { + for (int j = 0; j < 1000; ++j) { + uint64_t rangebits = ctx1.randbits(bits); + BOOST_CHECK_EQUAL(rangebits >> bits, 0); + uint64_t range = ((uint64_t)1) << bits | rangebits; + uint64_t rand = ctx2.randrange(range); + BOOST_CHECK(rand < range); + } + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index 19f4e0faeb6a..0a5cb1a8575f 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -32,7 +32,8 @@ #include -FastRandomContext insecure_rand_ctx(true); +uint256 insecure_rand_seed = GetRandHash(); +FastRandomContext insecure_rand_ctx(insecure_rand_seed); extern bool fPrintToConsole; extern void noui_connect(); diff --git a/src/test/test_random.h b/src/test/test_random.h index e61b92b7bce9..d1fae70458c7 100644 --- a/src/test/test_random.h +++ b/src/test/test_random.h @@ -8,11 +8,17 @@ #include "random.h" +extern uint256 insecure_rand_seed; extern FastRandomContext insecure_rand_ctx; static inline void seed_insecure_rand(bool fDeterministic = false) { - insecure_rand_ctx = FastRandomContext(fDeterministic); + if (fDeterministic) { + insecure_rand_seed = uint256(); + } else { + insecure_rand_seed = GetRandHash(); + } + insecure_rand_ctx = FastRandomContext(insecure_rand_seed); } static inline uint32_t insecure_rand(void) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d240c90f8573..aa209c4bb1c3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2635,7 +2635,7 @@ static void ApproximateBestSubset(const std::vector& vValue, const C //that the rng is fast. We do not use a constant random sequence, //because there may be some privacy improvement by making //the selection random. - if (nPass == 0 ? insecure_rand.rand32()&1 : !vfIncluded[i]) + if (nPass == 0 ? insecure_rand.randbool() : !vfIncluded[i]) { nTotal += vValue[i].txout.nValue; vfIncluded[i] = true; From f6c5d5802955b78a1614f7cfc07a7a3d3f125a12 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 25 Apr 2017 09:03:06 +0200 Subject: [PATCH 162/987] Merge #10272: [Tests] Prevent warning: variable 'x' is uninitialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 5ec8836 Prevent warning: variable 'x' is uninitialized (Pavel Janík) Tree-SHA512: 54e39d4b85303db033bd08c52ff2fa093ec9a1b1b9550911bb2123be60fa471cba81f36859681170695dfafb3a8a4c154122917c05b5a23837cf97c25907afc1 --- src/bench/crypto_hash.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bench/crypto_hash.cpp b/src/bench/crypto_hash.cpp index 27dbbf62b490..1b0d1fa75e22 100644 --- a/src/bench/crypto_hash.cpp +++ b/src/bench/crypto_hash.cpp @@ -92,7 +92,7 @@ static void HASH_SipHash_0032b(benchmark::State& state) static void FastRandom_32bit(benchmark::State& state) { FastRandomContext rng(true); - uint32_t x; + uint32_t x = 0; while (state.KeepRunning()) { for (int i = 0; i < 1000000; i++) { x += rng.rand32(); @@ -103,7 +103,7 @@ static void FastRandom_32bit(benchmark::State& state) static void FastRandom_1bit(benchmark::State& state) { FastRandomContext rng(true); - uint32_t x; + uint32_t x = 0; while (state.KeepRunning()) { for (int i = 0; i < 1000000; i++) { x += rng.randbool(); From 5bde530fa9bcb6a57db9f0527872b1eb1149077f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 25 Apr 2017 12:04:24 +0200 Subject: [PATCH 163/987] Merge #10270: Remove Clang workaround for Boost 1.46 93dbb15 Remove Clang workaround for Boost 1.46 (fanquake) Tree-SHA512: 1246841b264688f5fe5a2a514dd732d400307fa068686857e8aedaebb292ae65b21ab96b5ff9477ccd2f049882b967b6e143683963ce1be0b9e781596c5372d1 --- src/util.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 3f89b7b740f9..833f79fe2b5a 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -95,19 +95,6 @@ #include #include -// Work around clang compilation problem in Boost 1.46: -// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup -// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options -// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION -namespace boost { - - namespace program_options { - std::string to_internal(const std::string&); - } - -} // namespace boost - - //Dash only features bool fMasternodeMode = false; From 95e30b2ff72b71601433aae477d00701153a4502 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 25 Apr 2017 13:28:07 +0200 Subject: [PATCH 164/987] Merge #10263: Trivial: fix fee estimate write error log message 94807be Trivial: fix fee estimate write error log message (CryptAxe) Tree-SHA512: 998c9b331e901562c9ba575a85bc6c66f28d926dfe8116f08ab903e024c63a13fd37a58d19eb6504ad880d5bbccfbf6cba83ba0a6917f5d9068c52114f71b437 --- src/policy/fees.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index a14316aa7570..41e0e5393844 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -584,7 +584,7 @@ bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const feeStats->Write(fileout); } catch (const std::exception&) { - LogPrintf("CBlockPolicyEstimator::Write(): unable to read policy estimator data (non-fatal)\n"); + LogPrintf("CBlockPolicyEstimator::Write(): unable to write policy estimator data (non-fatal)\n"); return false; } return true; From db2f8cb131114b902697c91ff38f17d9c01d77db Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 25 Apr 2017 16:05:20 +0200 Subject: [PATCH 165/987] Merge #10225: [test] Add aborttrescan tests ed60970 [test] Test abortrescan command. (Karl-Johan Alm) Tree-SHA512: 7f617adba65a6df8fdc4b01432992926a06c4a05da4e657653436f7716301fa5d6249d77894a097737e7fb9e118925883f2425c639058b8973680339bb8e61b6 --- test/functional/import-abort-rescan.py | 66 ++++++++++++++++++++++++++ test/functional/test_runner.py | 1 + 2 files changed, 67 insertions(+) create mode 100755 test/functional/import-abort-rescan.py diff --git a/test/functional/import-abort-rescan.py b/test/functional/import-abort-rescan.py new file mode 100755 index 000000000000..ffe45bbb1df6 --- /dev/null +++ b/test/functional/import-abort-rescan.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test wallet import RPCs. + +Test rescan behavior of importprivkey when aborted. The test ensures that: +1. The abortrescan command indeed stops the rescan process. +2. Subsequent rescan catches the aborted address UTXO +""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import (assert_equal, get_rpc_proxy) +from decimal import Decimal +import threading # for bg importprivkey +import time # for sleep + +class ImportAbortRescanTest(BitcoinTestFramework): + def __init__(self): + super().__init__() + self.setup_clean_chain = True + + def run_test(self): + # Generate for BTC + assert_equal(self.nodes[0].getbalance(), 0) + assert_equal(self.nodes[1].getbalance(), 0) + self.nodes[0].generate(300) + assert_equal(self.nodes[1].getbalance(), 0) + # Make blocks with spam to cause rescan delay + for i in range(5): + for j in range(5): + self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.1) + self.nodes[0].generate(10) + addr = self.nodes[0].getnewaddress() + privkey = self.nodes[0].dumpprivkey(addr) + self.nodes[0].sendtoaddress(addr, 0.123) + self.nodes[0].generate(10) # mature tx + self.sync_all() + + # Import this address in the background ... + node1ref = get_rpc_proxy(self.nodes[1].url, 1, timeout=600) + importthread = threading.Thread(target=node1ref.importprivkey, args=[privkey]) + importthread.start() + # ... then abort rescan; try a bunch until abortres becomes true, + # because we will start checking before above thread starts processing + for i in range(2000): + time.sleep(0.001) + abortres = self.nodes[1].abortrescan() + if abortres: break + assert abortres # if false, we failed to abort + # import should die soon + for i in range(10): + time.sleep(0.1) + deadres = not importthread.isAlive() + if deadres: break + + assert deadres # if false, importthread did not die soon enough + assert_equal(self.nodes[1].getbalance(), 0.0) + + # Import a different address and let it run + self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())) + # Expect original privkey to now also be discovered and added to balance + assert_equal(self.nodes[1].getbalance(), Decimal("0.123")) + +if __name__ == "__main__": + ImportAbortRescanTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 0e0d07ced890..a21fa30e788b 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -99,6 +99,7 @@ 'rpcnamedargs.py', 'listsinceblock.py', 'p2p-leaktests.py', + 'import-abort-rescan.py', 'p2p-compactblocks.py', 'sporks.py', 'p2p-fingerprint.py', From b9ccc7dd6a3686ca81b12b35cd5269dd9a4c212c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 26 Apr 2017 08:49:22 +0200 Subject: [PATCH 166/987] Merge #9930: Trivial: Correct indentation and bracing 31a14d4 Correct indentation and remove unnecessary braces (Matthias Grundmann) Tree-SHA512: c0e827ec4474133c7674254dfd13f59608820cd639debc7759bddae71d73451645fcfe14384f343d08f74d69ac3922bafc12a514f3b790ae2bf9271aa67d5f36 --- src/net.cpp | 98 +++++++++++++------------- src/net.h | 6 +- src/net_processing.cpp | 154 ++++++++++++++++++++--------------------- 3 files changed, 127 insertions(+), 131 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index ce125ac95045..de045e2cc3bb 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -738,7 +738,7 @@ bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete } if (handled < 0) - return false; + return false; if (msg.in_data && msg.hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) { LogPrint(BCLog::NET, "Oversized message from peer=%i, disconnecting\n", GetId()); @@ -816,7 +816,7 @@ int CNetMessage::readHeader(const char *pch, unsigned int nBytes) // reject messages larger than MAX_SIZE if (hdr.nMessageSize > MAX_SIZE) - return -1; + return -1; // switch state to reading message data in_data = true; @@ -1394,59 +1394,55 @@ void CConnman::ThreadSocketHandler() } if (recvSet || errorSet) { + // typical socket buffer is 8K-64K + char pchBuf[0x10000]; + int nBytes = 0; { - { - // typical socket buffer is 8K-64K - char pchBuf[0x10000]; - int nBytes = 0; - { - LOCK(pnode->cs_hSocket); - if (pnode->hSocket == INVALID_SOCKET) - continue; - nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); - } - if (nBytes > 0) - { - bool notify = false; - if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify)) - pnode->CloseSocketDisconnect(); - RecordBytesRecv(nBytes); - if (notify) { - size_t nSizeAdded = 0; - auto it(pnode->vRecvMsg.begin()); - for (; it != pnode->vRecvMsg.end(); ++it) { - if (!it->complete()) - break; - nSizeAdded += it->vRecv.size() + CMessageHeader::HEADER_SIZE; - } - { - LOCK(pnode->cs_vProcessMsg); - pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it); - pnode->nProcessQueueSize += nSizeAdded; - pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize; - } - WakeMessageHandler(); - } - } - else if (nBytes == 0) - { - // socket closed gracefully - if (!pnode->fDisconnect) { - LogPrint(BCLog::NET, "socket closed\n"); - } - pnode->CloseSocketDisconnect(); + LOCK(pnode->cs_hSocket); + if (pnode->hSocket == INVALID_SOCKET) + continue; + nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); + } + if (nBytes > 0) + { + bool notify = false; + if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify)) + pnode->CloseSocketDisconnect(); + RecordBytesRecv(nBytes); + if (notify) { + size_t nSizeAdded = 0; + auto it(pnode->vRecvMsg.begin()); + for (; it != pnode->vRecvMsg.end(); ++it) { + if (!it->complete()) + break; + nSizeAdded += it->vRecv.size() + CMessageHeader::HEADER_SIZE; } - else if (nBytes < 0) { - // error - int nErr = WSAGetLastError(); - if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) - { - if (!pnode->fDisconnect) - LogPrintf("socket recv error %s\n", NetworkErrorString(nErr)); - pnode->CloseSocketDisconnect(); - } + LOCK(pnode->cs_vProcessMsg); + pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it); + pnode->nProcessQueueSize += nSizeAdded; + pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize; } + WakeMessageHandler(); + } + } + else if (nBytes == 0) + { + // socket closed gracefully + if (!pnode->fDisconnect) { + LogPrint(BCLog::NET, "socket closed\n"); + } + pnode->CloseSocketDisconnect(); + } + else if (nBytes < 0) + { + // error + int nErr = WSAGetLastError(); + if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) + { + if (!pnode->fDisconnect) + LogPrintf("socket recv error %s\n", NetworkErrorString(nErr)); + pnode->CloseSocketDisconnect(); } } } diff --git a/src/net.h b/src/net.h index 624ac433250b..f97b3e67ad7c 100644 --- a/src/net.h +++ b/src/net.h @@ -871,15 +871,15 @@ class CNode public: NodeId GetId() const { - return id; + return id; } uint64_t GetLocalNonce() const { - return nLocalHostNonce; + return nLocalHostNonce; } int GetMyStartingHeight() const { - return nMyStartingHeight; + return nMyStartingHeight; } int GetRefCount() diff --git a/src/net_processing.cpp b/src/net_processing.cpp index db26aae38ac5..9b48d41939e7 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3136,97 +3136,97 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic& i // this maintains the order of responses if (!pfrom->vRecvGetData.empty()) return true; - // Don't bother if send buffer is too full to respond anyway - if (pfrom->fPauseSend) - return false; + // Don't bother if send buffer is too full to respond anyway + if (pfrom->fPauseSend) + return false; - std::list msgs; - { - LOCK(pfrom->cs_vProcessMsg); - if (pfrom->vProcessMsg.empty()) - return false; - // Just take one message - msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin()); - pfrom->nProcessQueueSize -= msgs.front().vRecv.size() + CMessageHeader::HEADER_SIZE; - pfrom->fPauseRecv = pfrom->nProcessQueueSize > connman.GetReceiveFloodSize(); - fMoreWork = !pfrom->vProcessMsg.empty(); - } - CNetMessage& msg(msgs.front()); - - msg.SetVersion(pfrom->GetRecvVersion()); - // Scan for message start - if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { - LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id); - pfrom->fDisconnect = true; + std::list msgs; + { + LOCK(pfrom->cs_vProcessMsg); + if (pfrom->vProcessMsg.empty()) return false; - } + // Just take one message + msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin()); + pfrom->nProcessQueueSize -= msgs.front().vRecv.size() + CMessageHeader::HEADER_SIZE; + pfrom->fPauseRecv = pfrom->nProcessQueueSize > connman.GetReceiveFloodSize(); + fMoreWork = !pfrom->vProcessMsg.empty(); + } + CNetMessage& msg(msgs.front()); + + msg.SetVersion(pfrom->GetRecvVersion()); + // Scan for message start + if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { + LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id); + pfrom->fDisconnect = true; + return false; + } - // Read header - CMessageHeader& hdr = msg.hdr; - if (!hdr.IsValid(chainparams.MessageStart())) - { - LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id); - return fMoreWork; - } - std::string strCommand = hdr.GetCommand(); + // Read header + CMessageHeader& hdr = msg.hdr; + if (!hdr.IsValid(chainparams.MessageStart())) + { + LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id); + return fMoreWork; + } + std::string strCommand = hdr.GetCommand(); - // Message size - unsigned int nMessageSize = hdr.nMessageSize; + // Message size + unsigned int nMessageSize = hdr.nMessageSize; + + // Checksum + CDataStream& vRecv = msg.vRecv; + const uint256& hash = msg.GetMessageHash(); + if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) + { + LogPrintf("%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__, + SanitizeString(strCommand), nMessageSize, + HexStr(hash.begin(), hash.begin()+CMessageHeader::CHECKSUM_SIZE), + HexStr(hdr.pchChecksum, hdr.pchChecksum+CMessageHeader::CHECKSUM_SIZE)); + return fMoreWork; + } - // Checksum - CDataStream& vRecv = msg.vRecv; - const uint256& hash = msg.GetMessageHash(); - if (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) != 0) + // Process message + bool fRet = false; + try + { + fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams, connman, interruptMsgProc); + if (interruptMsgProc) + return false; + if (!pfrom->vRecvGetData.empty()) + fMoreWork = true; + } + catch (const std::ios_base::failure& e) + { + connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message"))); + if (strstr(e.what(), "end of data")) { - LogPrintf("%s(%s, %u bytes): CHECKSUM ERROR expected %s was %s\n", __func__, - SanitizeString(strCommand), nMessageSize, - HexStr(hash.begin(), hash.begin()+CMessageHeader::CHECKSUM_SIZE), - HexStr(hdr.pchChecksum, hdr.pchChecksum+CMessageHeader::CHECKSUM_SIZE)); - return fMoreWork; + // Allow exceptions from under-length message on vRecv + LogPrintf("%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } - - // Process message - bool fRet = false; - try + else if (strstr(e.what(), "size too large")) { - fRet = ProcessMessage(pfrom, strCommand, vRecv, msg.nTime, chainparams, connman, interruptMsgProc); - if (interruptMsgProc) - return false; - if (!pfrom->vRecvGetData.empty()) - fMoreWork = true; + // Allow exceptions from over-long size + LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); } - catch (const std::ios_base::failure& e) + else if (strstr(e.what(), "non-canonical ReadCompactSize()")) { - connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message"))); - if (strstr(e.what(), "end of data")) - { - // Allow exceptions from under-length message on vRecv - LogPrintf("%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); - } - else if (strstr(e.what(), "size too large")) - { - // Allow exceptions from over-long size - LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); - } - else if (strstr(e.what(), "non-canonical ReadCompactSize()")) - { - // Allow exceptions from non-canonical encoding - LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); - } - else - { - PrintExceptionContinue(std::current_exception(), "ProcessMessages()"); + // Allow exceptions from non-canonical encoding + LogPrintf("%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what()); + } + else + { + PrintExceptionContinue(std::current_exception(), "ProcessMessages()"); } } catch (...) { - PrintExceptionContinue(std::current_exception(), "ProcessMessages()"); - } + PrintExceptionContinue(std::current_exception(), "ProcessMessages()"); + } - if (!fRet) { - LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->id); - } + if (!fRet) { + LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->id); + } - LOCK(cs_main); - SendRejectsAndCheckIfBanned(pfrom, connman); + LOCK(cs_main); + SendRejectsAndCheckIfBanned(pfrom, connman); return fMoreWork; } From 1dec8e6933b80cc5797710154d347cfd41847f87 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 26 Apr 2017 09:34:08 +0200 Subject: [PATCH 167/987] Merge #10278: [test] Add Unit Test for GetListenPort 1b14449 [test] Add Unit Test for GetListenPort (Jimmy Song) Tree-SHA512: aea5f60fb3699680cc5acac9d9c8d8712634db9d629bbfa1815a29e5cf46c22f783886c608664baaa91b3282c52ce8069c358850cf4f90acf731a9e6c1701caa --- src/test/net_tests.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 7a319570440d..ea3ea35a4ac7 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -11,6 +11,7 @@ #include "net.h" #include "netbase.h" #include "chainparams.h" +#include "util.h" class CAddrManSerializationMock : public CAddrMan { @@ -72,6 +73,18 @@ CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman) BOOST_FIXTURE_TEST_SUITE(net_tests, BasicTestingSetup) +BOOST_AUTO_TEST_CASE(cnode_listen_port) +{ + // test default + unsigned short port = GetListenPort(); + BOOST_CHECK(port == Params().GetDefaultPort()); + // test set port + unsigned short altPort = 12345; + SoftSetArg("-port", std::to_string(altPort)); + port = GetListenPort(); + BOOST_CHECK(port == altPort); +} + BOOST_AUTO_TEST_CASE(caddrdb_read) { CAddrManUncorrupted addrmanUncorrupted; From ef84ea4fc1752b180c31aaa82655e0f8bb1772ea Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 26 Apr 2017 12:24:48 +0200 Subject: [PATCH 168/987] Merge #9743: Fix several potential issues found by sanitizers 1d31093 fix tsan: utiltime race on nMockTime (Pieter Wuille) 321bbc2 fix ubsan: bitcoin-tx: not initialize context before IsFullyValid (Pieter Wuille) Tree-SHA512: 39ea83c6122f06339cd425deb236357694e84ce2e4e9c61c10b90a8909b6e42e8c7b76396175cdc4723ababd2fa4f935d48f8a469baf853c5a06d7b962a5c8dc --- src/dash-tx.cpp | 8 +++++--- src/utiltime.cpp | 12 ++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/dash-tx.cpp b/src/dash-tx.cpp index 3af107e818db..e93a003842a6 100644 --- a/src/dash-tx.cpp +++ b/src/dash-tx.cpp @@ -624,11 +624,13 @@ static void MutateTx(CMutableTransaction& tx, const std::string& command, MutateTxDelOutput(tx, commandVal); else if (command == "outaddr") MutateTxAddOutAddr(tx, commandVal); - else if (command == "outpubkey") + else if (command == "outpubkey") { + if (!ecc) { ecc.reset(new Secp256k1Init()); } MutateTxAddOutPubKey(tx, commandVal); - else if (command == "outmultisig") + } else if (command == "outmultisig") { + if (!ecc) { ecc.reset(new Secp256k1Init()); } MutateTxAddOutMultiSig(tx, commandVal); - else if (command == "outscript") + } else if (command == "outscript") MutateTxAddOutScript(tx, commandVal); else if (command == "outdata") MutateTxAddOutData(tx, commandVal); diff --git a/src/utiltime.cpp b/src/utiltime.cpp index 41714ceead60..eb866924fe3f 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -10,14 +10,17 @@ #include "tinyformat.h" #include "utiltime.h" +#include + #include #include -static int64_t nMockTime = 0; //!< For unit testing +static std::atomic nMockTime(0); //!< For unit testing int64_t GetTime() { - if (nMockTime) return nMockTime; + int64_t mocktime = nMockTime.load(std::memory_order_relaxed); + if (mocktime) return mocktime; time_t now = time(NULL); assert(now > 0); @@ -26,7 +29,7 @@ int64_t GetTime() void SetMockTime(int64_t nMockTimeIn) { - nMockTime = nMockTimeIn; + nMockTime.store(nMockTimeIn, std::memory_order_relaxed); } bool IsMockTime() @@ -58,7 +61,8 @@ int64_t GetSystemTimeInSeconds() /** Return a time useful for the debug log */ int64_t GetLogTimeMicros() { - if (nMockTime) return nMockTime*1000000; + int64_t mocktime = nMockTime.load(std::memory_order_relaxed); + if (mocktime) return mocktime*1000000; return GetTimeMicros(); } From e03538778383782be12acd279ab761caf80b8166 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 14 Jun 2019 13:04:19 +0200 Subject: [PATCH 169/987] Back off for 1m when connecting to quorum masternodes (#2975) * Implement GetAddressInfo in CAddrMan * Back off for 1m when connecting to quorum masternodes --- src/addrman.cpp | 17 +++++++++++++++++ src/addrman.h | 15 +++++++++++++++ src/net.cpp | 7 +++++++ 3 files changed, 39 insertions(+) diff --git a/src/addrman.cpp b/src/addrman.cpp index 48b8dabd311a..75bf4b42c4c2 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -533,6 +533,23 @@ void CAddrMan::SetServices_(const CService& addr, ServiceFlags nServices) info.nServices = nServices; } +CAddrInfo CAddrMan::GetAddressInfo_(const CService& addr) +{ + CAddrInfo* pinfo = Find(addr); + + // if not found, bail out + if (!pinfo) + return CAddrInfo(); + + CAddrInfo& info = *pinfo; + + // check whether we are talking about the exact same CService (including same port) + if (info != addr) + return CAddrInfo(); + + return *pinfo; +} + int CAddrMan::RandomInt(int nMax){ return GetRandInt(nMax); } \ No newline at end of file diff --git a/src/addrman.h b/src/addrman.h index 413bf45277b5..600a0a4a77e8 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -265,6 +265,9 @@ class CAddrMan //! Update an entry's service bits. void SetServices_(const CService &addr, ServiceFlags nServices); + //! Get address info for address + CAddrInfo GetAddressInfo_(const CService& addr); + public: /** * serialized format: @@ -595,6 +598,18 @@ class CAddrMan Check(); } + CAddrInfo GetAddressInfo(const CService& addr) + { + CAddrInfo addrRet; + { + LOCK(cs); + Check(); + addrRet = GetAddressInfo_(addr); + Check(); + } + return addrRet; + } + }; #endif // BITCOIN_ADDRMAN_H diff --git a/src/net.cpp b/src/net.cpp index a859f1b56dc6..426abff56b30 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2072,6 +2072,8 @@ void CConnman::ThreadOpenMasternodeConnections() if (interruptNet) return; + int64_t nANow = GetAdjustedTime(); + // NOTE: Process only one pending masternode at a time CService addr; @@ -2087,6 +2089,11 @@ void CConnman::ThreadOpenMasternodeConnections() } const auto& addr2 = dmn->pdmnState->addr; if (!connectedNodes.count(addr2) && !IsMasternodeOrDisconnectRequested(addr2) && !connectedProRegTxHashes.count(proRegTxHash)) { + auto addrInfo = addrman.GetAddressInfo(addr2); + // back off trying connecting to an address if we already tried recently + if (addrInfo.IsValid() && nANow - addrInfo.nLastTry < 60) { + continue; + } pending.emplace_back(addr2); } } From 6332310922b4dfc87c4aa3c6bc4a740a28ffcee6 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 14 Jun 2019 14:04:50 +0300 Subject: [PATCH 170/987] Provide correct params to AcceptToMemoryPoolWithTime() in LoadMempool() (#2976) Introduced in 2971 --- src/validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index b2f052338bd7..5a7d8de1dc43 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4635,7 +4635,7 @@ bool LoadMempool(void) CValidationState state; if (nTime + nExpiryTimeout > nNow) { LOCK(cs_main); - AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, true, NULL, nTime, NULL, false, 0); + AcceptToMemoryPoolWithTime(chainparams, mempool, state, tx, true, NULL, nTime, false, 0, false); if (state.IsValid()) { ++count; } else { From 94c79e8691f8c06c12751bcbdc905735c17ea538 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 26 Apr 2017 23:48:44 +0200 Subject: [PATCH 171/987] Merge #10280: [test] Unit test amount.h/amount.cpp dcb69fd [test] Unit test amount.h/amount.cpp (Jimmy Song) Tree-SHA512: dc50e6158322a282a8b8b60c8eab7ce327a33c48113a1455b8a1784f07e6277ad499e85ec978199468a2dc34e9e288287c8803c215f810fa2d841cdda9a414f5 btc to dash Signed-off-by: Pasta btc -> DASH 10280 Signed-off-by: Pasta --- src/test/amount_tests.cpp | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 4baee4301acd..4fb1d276b4ee 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -9,9 +9,16 @@ BOOST_FIXTURE_TEST_SUITE(amount_tests, BasicTestingSetup) +BOOST_AUTO_TEST_CASE(MoneyRangeTest) +{ + BOOST_CHECK_EQUAL(MoneyRange(CAmount(-1)), false); + BOOST_CHECK_EQUAL(MoneyRange(MAX_MONEY + CAmount(1)), false); + BOOST_CHECK_EQUAL(MoneyRange(CAmount(1)), true); +} + BOOST_AUTO_TEST_CASE(GetFeeTest) { - CFeeRate feeRate; + CFeeRate feeRate, altFeeRate; feeRate = CFeeRate(0); // Must always return 0 @@ -53,6 +60,11 @@ BOOST_AUTO_TEST_CASE(GetFeeTest) BOOST_CHECK_EQUAL(feeRate.GetFee(8), -1); // Special case: returns -1 instead of 0 BOOST_CHECK_EQUAL(feeRate.GetFee(9), -1); + // check alternate constructor + feeRate = CFeeRate(1000); + altFeeRate = CFeeRate(feeRate); + BOOST_CHECK_EQUAL(feeRate.GetFee(100), altFeeRate.GetFee(100)); + // Check full constructor // default value BOOST_CHECK(CFeeRate(CAmount(-1), 1000) == CFeeRate(-1)); @@ -68,4 +80,28 @@ BOOST_AUTO_TEST_CASE(GetFeeTest) CFeeRate(MAX_MONEY, std::numeric_limits::max() >> 1).GetFeePerK(); } +BOOST_AUTO_TEST_CASE(BinaryOperatorTest) +{ + CFeeRate a, b; + a = CFeeRate(1); + b = CFeeRate(2); + BOOST_CHECK(a < b); + BOOST_CHECK(b > a); + BOOST_CHECK(a == a); + BOOST_CHECK(a <= b); + BOOST_CHECK(a <= a); + BOOST_CHECK(b >= a); + BOOST_CHECK(b >= b); + // a should be 0.00000002 DASH/kB now + a += a; + BOOST_CHECK(a == b); +} + +BOOST_AUTO_TEST_CASE(ToStringTest) +{ + CFeeRate feeRate; + feeRate = CFeeRate(1); + BOOST_CHECK_EQUAL(feeRate.ToString(), "0.00000001 DASH/kB"); +} + BOOST_AUTO_TEST_SUITE_END() From d9ac44740f24a3fc120fbd69e0e4656532a19a34 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 27 Apr 2017 09:09:28 -0700 Subject: [PATCH 172/987] Merge #10283: Cleanup: reduce to one GetMinimumFee call signature 3edbd79 cleanup: reduce to one GetMinimumFee call signature (Alex Morcos) Tree-SHA512: da7ae6f0eb06db630792243a47c95d4ceff3baf0ce1ebefa73f1eb6cab1c6fdf0a000770cf61700dd7a9e260d7a313083b79e1d667bd5cbef0b1fe8fbec411e7 --- src/wallet/wallet.cpp | 11 +++-------- src/wallet/wallet.h | 7 +------ 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index aa209c4bb1c3..12915a1015dc 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3850,17 +3850,12 @@ CAmount CWallet::GetRequiredFee(unsigned int nTxBytes) return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes)); } -CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator) +CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, bool ignoreUserSetFee) { // payTxFee is the user-set global for desired feerate - return GetMinimumFee(nTxBytes, nConfirmTarget, pool, estimator, payTxFee.GetFee(nTxBytes)); -} - -CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, CAmount targetFee) -{ - CAmount nFeeNeeded = targetFee; + CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes); // User didn't set: use -txconfirmtarget to estimate... - if (nFeeNeeded == 0) { + if (nFeeNeeded == 0 || ignoreUserSetFee) { int estimateFoundTarget = nConfirmTarget; nFeeNeeded = estimator.estimateSmartFee(nConfirmTarget, &estimateFoundTarget, pool).GetFee(nTxBytes); // ... unless we don't have enough mempool data for estimatefee, then use fallbackFee diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index aee2961a4cb8..95120d27af24 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1057,12 +1057,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * Estimate the minimum fee considering user set parameters * and the required fee */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator); - /** - * Estimate the minimum fee considering required fee and targetFee or if 0 - * then fee estimation for nConfirmTarget - */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, CAmount targetFee); + static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, const CBlockPolicyEstimator& estimator, bool ignoreUserSetFee = false); /** * Return the minimum required fee taking into account the * floating relay fee and user set minimum transaction fee From ed68d2ca1290ae3768424101ca510ce1bdc0f7cc Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 27 Apr 2017 19:28:13 +0200 Subject: [PATCH 173/987] Merge #10075: Remove unused C++ code not covered by unit tests b51aaf1 Remove unused C++ code not covered by unit tests (practicalswift) Tree-SHA512: 267bbd87df01a296bf23e82a8b6ee968e13e23a6aaecc535d803890a3e3e9f6208c7fc4c1f97afd98ed3e498b12fe1ada7e3cb2977ad12359a813f57336c74e5 --- src/chainparamsbase.cpp | 5 ----- src/chainparamsbase.h | 6 ------ src/key.cpp | 8 -------- src/key.h | 3 --- src/netaddress.cpp | 6 ------ src/netaddress.h | 1 - src/script/interpreter.cpp | 6 +++--- src/wallet/db.cpp | 9 --------- src/wallet/db.h | 1 - 9 files changed, 3 insertions(+), 42 deletions(-) diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 80a00654dfde..9353f7772e79 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -144,8 +144,3 @@ std::string GetDevNetName() std::string devNetName = GetArg("-devnet", ""); return "devnet" + (devNetName.empty() ? "" : "-" + devNetName); } - -bool AreBaseParamsConfigured() -{ - return pCurrentBaseParams != NULL; -} diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 412f3551aadf..780a35a25519 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -56,10 +56,4 @@ std::string ChainNameFromCommandLine(); std::string GetDevNetName(); -/** - * Return true if SelectBaseParamsFromCommandLine() has been called to select - * a network. - */ -bool AreBaseParamsConfigured(); - #endif // BITCOIN_CHAINPARAMSBASE_H diff --git a/src/key.cpp b/src/key.cpp index b3ea98fb92e6..5f4cda26da13 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -131,14 +131,6 @@ void CKey::MakeNewKey(bool fCompressedIn) { fCompressed = fCompressedIn; } -bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) { - if (!ec_privkey_import_der(secp256k1_context_sign, (unsigned char*)begin(), &privkey[0], privkey.size())) - return false; - fCompressed = fCompressedIn; - fValid = true; - return true; -} - CPrivKey CKey::GetPrivKey() const { assert(fValid); CPrivKey privkey; diff --git a/src/key.h b/src/key.h index b218f2cb7222..cf9f99aafb4b 100644 --- a/src/key.h +++ b/src/key.h @@ -94,9 +94,6 @@ class CKey //! Check whether the public key corresponding to this private key is (to be) compressed. bool IsCompressed() const { return fCompressed; } - //! Initialize from a CPrivKey (serialized OpenSSL private key data). - bool SetPrivKey(const CPrivKey& vchPrivKey, bool fCompressed); - //! Generate a new private key using a cryptographic PRNG. void MakeNewKey(bool fCompressed); diff --git a/src/netaddress.cpp b/src/netaddress.cpp index c9742989216e..c9456ff582ce 100644 --- a/src/netaddress.cpp +++ b/src/netaddress.cpp @@ -182,12 +182,6 @@ bool CNetAddr::IsLocal() const return false; } -bool CNetAddr::IsMulticast() const -{ - return (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0) - || (GetByte(15) == 0xFF); -} - bool CNetAddr::IsValid() const { // Cleanup 3-byte shifted addresses caused by garbage in size field diff --git a/src/netaddress.h b/src/netaddress.h index 85b7b94b3e9e..0c6166d7697b 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -67,7 +67,6 @@ class CNetAddr bool IsLocal() const; bool IsRoutable() const; bool IsValid() const; - bool IsMulticast() const; enum Network GetNetwork() const; std::string ToString() const; std::string ToStringIP(bool fUseGetnameinfo = true) const; diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index bc7e58acdd02..6633336fddae 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -231,10 +231,10 @@ bool EvalScript(std::vector >& stack, const CScript& { static const CScriptNum bnZero(0); static const CScriptNum bnOne(1); - static const CScriptNum bnFalse(0); - static const CScriptNum bnTrue(1); + // static const CScriptNum bnFalse(0); + // static const CScriptNum bnTrue(1); static const valtype vchFalse(0); - static const valtype vchZero(0); + // static const valtype vchZero(0); static const valtype vchTrue(1, 1); CScript::const_iterator pc = script.begin(); diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 98d6df3dc46d..fea26f3484b5 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -465,15 +465,6 @@ void CDBEnv::CloseDb(const std::string& strFile) } } -bool CDBEnv::RemoveDb(const std::string& strFile) -{ - this->CloseDb(strFile); - - LOCK(cs_db); - int rc = dbenv->dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT); - return (rc == 0); -} - bool CDB::Rewrite(CWalletDBWrapper& dbw, const char* pszSkip) { if (dbw.IsDummy()) { diff --git a/src/wallet/db.h b/src/wallet/db.h index c1fac5cada17..e4d8a5154d13 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -72,7 +72,6 @@ class CDBEnv void CheckpointLSN(const std::string& strFile); void CloseDb(const std::string& strFile); - bool RemoveDb(const std::string& strFile); DbTxn* TxnBegin(int flags = DB_TXN_WRITE_NOSYNC) { From c2dd5cd33998df14503aebf856901a3986c95281 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 29 Apr 2017 14:47:00 +0200 Subject: [PATCH 174/987] Merge #10256: [test] Add test for gettxout to wallet.py dd1ea59 [test] Add gettxout call (Jimmy Song) Tree-SHA512: 5cea3763de30ec09b6e28b5a0c70f44d0c72a5b6ce159fdc95c1d43689ccfd21a32002d075c47cf011f66e505d9b97ea679c7c8825081a078543472e3e5083fb adjust tests values * 10 Signed-off-by: Pasta --- test/functional/wallet.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/test/functional/wallet.py b/test/functional/wallet.py index 70c1b61ba67a..8a6637663e94 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -6,7 +6,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -class WalletTest (BitcoinTestFramework): +class WalletTest(BitcoinTestFramework): def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size): """Return curr_balance after asserting the fee was in range""" @@ -28,7 +28,7 @@ def setup_network(self, split=False): self.is_network_split=False self.sync_all() - def run_test (self): + def run_test(self): # Check that there's no UTXO on none of the nodes assert_equal(len(self.nodes[0].listunspent()), 0) @@ -52,14 +52,34 @@ def run_test (self): assert_equal(self.nodes[2].getbalance(), 0) # Check that only first and second nodes have UTXOs - assert_equal(len(self.nodes[0].listunspent()), 1) + utxos = self.nodes[0].listunspent() + assert_equal(len(utxos), 1) assert_equal(len(self.nodes[1].listunspent()), 1) assert_equal(len(self.nodes[2].listunspent()), 0) # Send 210 DASH from 0 to 2 using sendtoaddress call. # Second transaction will be child of first, and will require a fee self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 110) - self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 100) + mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 100) + + self.log.info("test gettxout") + # utxo spent in mempool should be visible if you exclude mempool + # but invisible if you include mempool + confirmed_txid, confirmed_index = utxos[0]["txid"], utxos[0]["vout"] + txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, False) + assert_equal(txout['value'], 500) + txout = self.nodes[0].gettxout(confirmed_txid, confirmed_index, True) + assert txout is None + # new utxo from mempool should be invisible if you exclude mempool + # but visible if you include mempool + txout = self.nodes[0].gettxout(mempool_txid, 0, False) + assert txout is None + txout1 = self.nodes[0].gettxout(mempool_txid, 0, True) + txout2 = self.nodes[0].gettxout(mempool_txid, 1, True) + # note the mempool tx will have randomly assigned indices + # but 10 will go to node2 and the rest will go to node0 + balance = self.nodes[0].getbalance() + assert_equal(set([txout1['value'], txout2['value']]), set([100, balance])) walletinfo = self.nodes[0].getwalletinfo() assert_equal(walletinfo['immature_balance'], 0) From 0326e21a80148d27c5690950e8198187733db114 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 1 May 2017 09:16:17 +0200 Subject: [PATCH 175/987] Merge #10290: Add -stopatheight for benchmarking b297426 Add -stopatheight for benchmarking (Pieter Wuille) Tree-SHA512: e8a4cca7fc1accd0dcd3a0eda97839fc34c61f25d6302082a8d6ecf9a0291b4abacbde16a0ecba7bdd2a56dd0c8d4d54300ad3b3478386da21dd7697acce381c --- src/init.cpp | 2 ++ src/validation.cpp | 3 +++ src/validation.h | 3 +++ 3 files changed, 8 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index ec056099e44e..05b511090874 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -557,6 +557,8 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-dropmessagestest=", "Randomly drop 1 of every network messages"); strUsage += HelpMessageOpt("-fuzzmessagestest=", "Randomly fuzz 1 of every network messages"); strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT)); + strUsage += HelpMessageOpt("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u)", DEFAULT_STOPATHEIGHT)); + strUsage += HelpMessageOpt("-limitancestorcount=", strprintf("Do not accept transactions if number of in-mempool ancestors is or more (default: %u)", DEFAULT_ANCESTOR_LIMIT)); strUsage += HelpMessageOpt("-limitancestorsize=", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT)); strUsage += HelpMessageOpt("-limitdescendantcount=", strprintf("Do not accept transactions if any ancestor would have or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT)); diff --git a/src/validation.cpp b/src/validation.cpp index b3ef4865a29b..a3ed30ab82e0 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2964,6 +2964,9 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return false; } + int nStopAtHeight = GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); + if (nStopAtHeight && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); + return true; } diff --git a/src/validation.h b/src/validation.h index a6a2b851b945..9384681b282b 100644 --- a/src/validation.h +++ b/src/validation.h @@ -146,6 +146,9 @@ static const int MAX_UNCONNECTING_HEADERS = 10; static const bool DEFAULT_PEERBLOOMFILTERS = true; +/** Default for -stopatheight */ +static const int DEFAULT_STOPATHEIGHT = 0; + struct BlockHasher { size_t operator()(const uint256& hash) const { return hash.GetCheapHash(); } From 82feee353ac2ede565a4c99a438b745201b93abf Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 1 May 2017 14:59:55 -0700 Subject: [PATCH 176/987] Merge #10305: Fix potential NPD introduced in b297426c 70d3945 Fix potential NPD introduced in b297426c (Matt Corallo) Tree-SHA512: 920d03d2081ba2f3447cfa655dcbc3e17858454dab051436f717ada977d4f4bfe999c303018bc8aa33f30e37a97c63d70ba08632f5e7b7a8aa555615dde2191a --- src/validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index a3ed30ab82e0..ffd528355124 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2965,7 +2965,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, } int nStopAtHeight = GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); - if (nStopAtHeight && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); + if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); return true; } From 717e0957ec18e7abe7e7cd9d3b1130fd45e2d681 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 1 May 2017 16:34:45 -0700 Subject: [PATCH 177/987] Merge #10292: Improved efficiency in COutPoint constructors 4fbae77 Improved efficiency in COutPoint constructors (Marcos Mayorga) Tree-SHA512: 1e402d5021a47724b6159af90955f1a5932c383f48e3e704f1c9a52daa18d2dce5d8e1fcd02fae6977eab04ab83fa22872110b821d4c6593d940d9642abc9bcd --- src/primitives/transaction.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 76cdc3463a57..832391556947 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -29,8 +29,8 @@ class COutPoint uint256 hash; uint32_t n; - COutPoint() { SetNull(); } - COutPoint(uint256 hashIn, uint32_t nIn) { hash = hashIn; n = nIn; } + COutPoint(): n((uint32_t) -1) { } + COutPoint(const uint256& hashIn, uint32_t nIn): hash(hashIn), n(nIn) { } ADD_SERIALIZE_METHODS; From f097b2d94d5a8c97915a156b0c830659c1a8d7d5 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 2 May 2017 07:52:34 +0200 Subject: [PATCH 178/987] Merge #10281: doc: Add RPC interface guidelines c26655e doc: Add RPC interface guidelines (Wladimir J. van der Laan) Tree-SHA512: e4cf1625d136fef9fe24361b6507c7e7ec2e676fb9727bbdcd4320aace6d0b49ce707592cb93a67b427168a1f373542e94bcea418b4e1c0cb1e9430af7412c8f --- doc/developer-notes.md | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 003ecb4948b9..6374637fe79d 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -497,3 +497,76 @@ Git and GitHub tips This will add an `upstream-pull` remote to your git repository, which can be fetched using `git fetch --all` or `git fetch upstream-pull`. Afterwards, you can use `upstream-pull/NUMBER/head` in arguments to `git show`, `git checkout` and anywhere a commit id would be acceptable to see the changes from pull request NUMBER. + +RPC interface guidelines +-------------------------- + +A few guidelines for introducing and reviewing new RPC interfaces: + +- Method naming: use consecutive lower-case names such as `getrawtransaction` and `submitblock` + + - *Rationale*: Consistency with existing interface. + +- Argument naming: use snake case `fee_delta` (and not, e.g. camel case `feeDelta`) + + - *Rationale*: Consistency with existing interface. + +- Use the JSON parser for parsing, don't manually parse integers or strings from + arguments unless absolutely necessary. + + - *Rationale*: Introduces hand-rolled string manipulation code at both the caller and callee sites, + which is error prone, and it is easy to get things such as escaping wrong. + JSON already supports nested data structures, no need to re-invent the wheel. + + - *Exception*: AmountToValue can parse amounts as string. This was introduced because many JSON + parsers and formatters hard-code handling decimal numbers as floating point + values, resulting in potential loss of precision. This is unacceptable for + monetary values. **Always** use `AmountToValue` and `ValueToAmount` when + inputting or outputting monetary values. The only exceptions to this are + `prioritisetransaction` and `getblocktemplate` because their interface + is specified as-is in BIP22. + +- Missing arguments and 'null' should be treated the same: as default values. If there is no + default value, both cases should fail in the same way. + + - *Rationale*: Avoids surprises when switching to name-based arguments. Missing name-based arguments + are passed as 'null'. + + - *Exception*: Many legacy exceptions to this exist, one of the worst ones is + `getbalance` which follows a completely different code path based on the + number of arguments. We are still in the process of cleaning these up. Do not introduce + new ones. + +- Try not to overload methods on argument type. E.g. don't make `getblock(true)` and `getblock("hash")` + do different things. + + - *Rationale*: This is impossible to use with `bitcoin-cli`, and can be surprising to users. + + - *Exception*: Some RPC calls can take both an `int` and `bool`, most notably when a bool was switched + to a multi-value, or due to other historical reasons. **Always** have false map to 0 and + true to 1 in this case. + +- Don't forget to fill in the argument names correctly in the RPC command table. + + - *Rationale*: If not, the call can not be used with name-based arguments. + +- Set okSafeMode in the RPC command table to a sensible value: safe mode is when the + blockchain is regarded to be in a confused state, and the client deems it unsafe to + do anything irreversible such as send. Anything that just queries should be permitted. + + - *Rationale*: Troubleshooting a node in safe mode is difficult if half the + RPCs don't work. + +- Add every non-string RPC argument `(method, idx, name)` to the table `vRPCConvertParams` in `rpc/client.cpp`. + + - *Rationale*: `bitcoin-cli` and the GUI debug console use this table to determine how to + convert a plaintext command line to JSON. If the types don't match, the method can be unusable + from there. + +- A RPC method must either be a wallet method or a non-wallet method. Do not + introduce new methods such as `getinfo` and `signrawtransaction` that differ + in behavior based on presence of a wallet. + + - *Rationale*: as well as complicating the implementation and interfering + with the introduction of multi-wallet, wallet and non-wallet code should be + separated to avoid introducing circular dependencies between code units. From 60aa17e0a9b15765ccc0595e9a74c693eda2db52 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 2 May 2017 14:47:53 +0200 Subject: [PATCH 179/987] =?UTF-8?q?Merge=20#10180:=20[trivial]=20Fix=20typ?= =?UTF-8?q?os=20(tempoarily=20=E2=86=92=20temporarily,=20inadvertantly=20?= =?UTF-8?q?=E2=86=92=20inadvertently)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 66082e0 [trivial] Fix typos (tempoarily → temporarily, inadvertantly → inadvertently) (practicalswift) Tree-SHA512: f377c379c9b6702894289c96fa50e64da01fa4e9353f8507ec5f1f58b0f3047fffdc473dffca61774f57793b82cf9e1c9b5f3d9a04fb864ccc1f44fc2a711f32 --- src/wallet/wallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 12915a1015dc..88558fbc51f7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1317,12 +1317,12 @@ void CWallet::TransactionAddedToMempool(const CTransactionRef& ptx) { void CWallet::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) { LOCK2(cs_main, cs_wallet); - // TODO: Tempoarily ensure that mempool removals are notified before + // TODO: Temporarily ensure that mempool removals are notified before // connected transactions. This shouldn't matter, but the abandoned // state of transactions in our wallet is currently cleared when we // receive another notification and there is a race condition where // notification of a connected conflict might cause an outside process - // to abandon a transaction and then have it inadvertantly cleared by + // to abandon a transaction and then have it inadvertently cleared by // the notification that the conflicted transaction was evicted. for (const CTransactionRef& ptx : vtxConflicted) { From ed71579ccec9c890dbb812cd108431bc4b521e6b Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 2 May 2017 14:56:55 +0200 Subject: [PATCH 180/987] Merge #10093: [Qt] Don't add arguments of sensitive command to console window 7278537 [Qt] Don't add arguments of sensitive command to console window (Jonas Schnelli) Tree-SHA512: 3e5aa19a3f157caf383a0fd7dbf9b0d298d31ddaf8e24e3d1a8b913e19f54f3b69e115f98a21f3e3a14e5ccb368b59de061490ed39718299456a04989f8e3366 --- src/qt/rpcconsole.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index f2ffd9edd712..13e2af93255a 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -937,7 +937,7 @@ void RPCConsole::on_lineEdit_returnPressed() cmdBeforeBrowsing = QString(); - message(CMD_REQUEST, cmd); + message(CMD_REQUEST, QString::fromStdString(strFilteredCmd)); Q_EMIT cmdRequest(cmd); cmd = QString::fromStdString(strFilteredCmd); From 146cae95693801ea65f7dcc141fad6b163e45034 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 2 May 2017 17:09:25 +0200 Subject: [PATCH 181/987] Merge #10234: [net] listbanned RPC and QT should show correct banned subnets d6732d8 [tests] update disconnect_ban.py test case to work with listbanned (John Newbery) 77c54b2 [net] listbanned RPC and QT should show correct banned subnets (John Newbery) Tree-SHA512: edd0e43377d456260d2697213c2829f8483630f3a668b6707d52605faefa610d951d10e6f22a95eff483cbd14faa8ac9b69fa7d3c0b5735c5f3df23fd71282e0 --- src/net.cpp | 8 +++++--- test/functional/disconnect_ban.py | 10 +++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index de045e2cc3bb..db8ce758933f 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -433,10 +433,10 @@ void CConnman::DumpBanlist() CBanDB bandb; banmap_t banmap; - SetBannedSetDirty(false); GetBanned(banmap); - if (!bandb.Write(banmap)) - SetBannedSetDirty(true); + if (bandb.Write(banmap)) { + SetBannedSetDirty(false); + } LogPrint(BCLog::NET, "Flushed %d banned node ips/subnets to banlist.dat %dms\n", banmap.size(), GetTimeMillis() - nStart); @@ -552,6 +552,8 @@ bool CConnman::Unban(const CSubNet &subNet) { void CConnman::GetBanned(banmap_t &banMap) { LOCK(cs_setBanned); + // Sweep the banlist so expired bans are not returned + SweepBanned(); banMap = setBanned; //create a thread safe copy } diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py index 5c168b80d9e9..91d183618042 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/disconnect_ban.py @@ -33,7 +33,7 @@ def run_test(self): self.log.info("setban: successfully ban single IP address") assert_equal(len(self.nodes[1].getpeerinfo()), 2) # node1 should have 2 connections to node0 at this point self.nodes[1].setban("127.0.0.1", "add") - wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0) + assert wait_until(lambda: len(self.nodes[1].getpeerinfo()) == 0, timeout=10) assert_equal(len(self.nodes[1].getpeerinfo()), 0) # all nodes must be disconnected at this point assert_equal(len(self.nodes[1].listbanned()), 1) @@ -69,7 +69,7 @@ def run_test(self): assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) set_mocktime(get_mocktime() + 2) set_node_times(self.nodes, get_mocktime()) - wait_until(lambda: len(self.nodes[1].listbanned()) == 3) + assert wait_until(lambda: len(self.nodes[1].listbanned()) == 3, timeout=10) stop_node(self.nodes[1], 1) @@ -83,7 +83,7 @@ def run_test(self): self.nodes[1].clearbanned() connect_nodes_bi(self.nodes, 0, 1) - self.log.info("Test disconnectrnode RPCs") + self.log.info("Test disconnectnode RPCs") self.log.info("disconnectnode: fail to disconnect when calling with address and nodeid") address1 = self.nodes[0].getpeerinfo()[0]['addr'] @@ -96,7 +96,7 @@ def run_test(self): self.log.info("disconnectnode: successfully disconnect node by address") address1 = self.nodes[0].getpeerinfo()[0]['addr'] self.nodes[0].disconnectnode(address=address1) - wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1) + assert wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10) assert not [node for node in self.nodes[0].getpeerinfo() if node['addr'] == address1] self.log.info("disconnectnode: successfully reconnect node") @@ -107,7 +107,7 @@ def run_test(self): self.log.info("disconnectnode: successfully disconnect node by node id") id1 = self.nodes[0].getpeerinfo()[0]['id'] self.nodes[0].disconnectnode(nodeid=id1) - wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1) + assert wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 1, timeout=10) assert not [node for node in self.nodes[0].getpeerinfo() if node['id'] == id1] if __name__ == '__main__': From 2d771c95a1186589df463ce4cf3bd8dfbe948c55 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 2 May 2017 19:10:23 +0200 Subject: [PATCH 182/987] Merge #10169: [tests] Remove func test code duplication 2a52ae6 Remove duplicate method definitions in NodeConnCB subclasses (John Newbery) 52e15aa Adds helper functions to NodeConnCB (John Newbery) Tree-SHA512: 2d7909eb85b3bde0fc3ebf133798eca21e561f4b2a2880937750820a42856cfb61fc94e30591c14ac13218bcfae0ebe7c5e8662a7b10f5b02470325c44a86cf1 remove duplicate code 10169 Signed-off-by: Pasta --- test/functional/maxuploadtarget.py | 76 ++-------- test/functional/p2p-acceptblock.py | 42 +----- test/functional/p2p-compactblocks.py | 162 ++++++++------------- test/functional/p2p-leaktests.py | 19 +-- test/functional/p2p-mempool.py | 62 +------- test/functional/p2p-timeouts.py | 15 +- test/functional/p2p-versionbits-warning.py | 18 --- test/functional/sendheaders.py | 99 ++++--------- test/functional/test_framework/comptool.py | 4 +- test/functional/test_framework/mininode.py | 140 ++++++++++++------ 10 files changed, 212 insertions(+), 425 deletions(-) diff --git a/test/functional/maxuploadtarget.py b/test/functional/maxuploadtarget.py index efc2cdb5a639..82455cb0c40a 100755 --- a/test/functional/maxuploadtarget.py +++ b/test/functional/maxuploadtarget.py @@ -10,63 +10,24 @@ if uploadtarget has been reached. * Verify that the upload counters are reset after 24 hours. """ +from collections import defaultdict +import time from test_framework.mininode import * from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import time -# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending -# p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): def __init__(self): super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() - self.block_receive_map = {} - - def add_connection(self, conn): - self.connection = conn - self.peer_disconnected = False + self.block_receive_map = defaultdict(int) def on_inv(self, conn, message): pass - # Track the last getdata message we receive (used in the test) - def on_getdata(self, conn, message): - self.last_getdata = message - def on_block(self, conn, message): message.block.calc_sha256() - try: - self.block_receive_map[message.block.sha256] += 1 - except KeyError as e: - self.block_receive_map[message.block.sha256] = 1 - - # Spin until verack message is received from the node. - # We use this to signal that our test can begin. This - # is called from the testing thread, so it needs to acquire - # the global lock. - def wait_for_verack(self): - def veracked(): - return self.verack_received - return wait_until(veracked, timeout=10) - - def wait_for_disconnect(self): - def disconnected(): - return self.peer_disconnected - return wait_until(disconnected, timeout=10) - - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_pong(self, conn, message): - self.last_pong = message - - def on_close(self, conn): - self.peer_disconnected = True + self.block_receive_map[message.block.sha256] += 1 class MaxUploadTest(BitcoinTestFramework): @@ -197,33 +158,26 @@ def run_test(self): stop_node(self.nodes[0], 0) self.nodes[0] = start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1", "-maxuploadtarget=1", "-blockmaxsize=999000", "-maxtipage="+str(2*60*60*24*7)]) - #recreate/reconnect 3 test nodes - test_nodes = [] - connections = [] - - for i in range(3): - test_nodes.append(TestNode()) - connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[i])) - test_nodes[i].add_connection(connections[i]) + #recreate/reconnect a test node + test_nodes = [TestNode()] + connections = [NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[0])] + test_nodes[0].add_connection(connections[0]) NetworkThread().start() # Start up network handling in another thread - [x.wait_for_verack() for x in test_nodes] + test_nodes[0].wait_for_verack() #retrieve 20 blocks which should be enough to break the 1MB limit getdata_request.inv = [CInv(2, big_new_block)] for i in range(20): - test_nodes[1].send_message(getdata_request) - test_nodes[1].sync_with_ping() - assert_equal(test_nodes[1].block_receive_map[big_new_block], i+1) + test_nodes[0].send_message(getdata_request) + test_nodes[0].sync_with_ping() + assert_equal(test_nodes[0].block_receive_map[big_new_block], i+1) getdata_request.inv = [CInv(2, big_old_block)] - test_nodes[1].send_message(getdata_request) - test_nodes[1].wait_for_disconnect() - assert_equal(len(self.nodes[0].getpeerinfo()), 3) #node is still connected because of the whitelist + test_nodes[0].send_and_ping(getdata_request) + assert_equal(len(self.nodes[0].getpeerinfo()), 1) #node is still connected because of the whitelist - self.log.info("Peer 1 still connected after trying to download old block (whitelisted)") - - [c.disconnect_node() for c in connections] + self.log.info("Peer still connected after trying to download old block (whitelisted)") if __name__ == '__main__': MaxUploadTest().main() diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p-acceptblock.py index 78b788d93f70..ebbc43dd1b4d 100755 --- a/test/functional/p2p-acceptblock.py +++ b/test/functional/p2p-acceptblock.py @@ -54,40 +54,6 @@ import time from test_framework.blocktools import create_block, create_coinbase -# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending -# p2p messages to a node, generating the messages in the main testing logic. -class TestNode(NodeConnCB): - def __init__(self): - super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() - - def add_connection(self, conn): - self.connection = conn - - # Track the last getdata message we receive (used in the test) - def on_getdata(self, conn, message): - self.last_getdata = message - - # Spin until verack message is received from the node. - # We use this to signal that our test can begin. This - # is called from the testing thread, so it needs to acquire - # the global lock. - def wait_for_verack(self): - while True: - with mininode_lock: - if self.verack_received: - return - time.sleep(0.05) - - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_pong(self, conn, message): - self.last_pong = message - class AcceptBlockTest(BitcoinTestFramework): def add_options(self, parser): parser.add_option("--testbinary", dest="testbinary", @@ -112,8 +78,8 @@ def setup_network(self): def run_test(self): # Setup the p2p connections and start up the network thread. - test_node = TestNode() # connects to node0 (not whitelisted) - white_node = TestNode() # connects to node1 (whitelisted) + test_node = NodeConnCB() # connects to node0 (not whitelisted) + white_node = NodeConnCB() # connects to node1 (whitelisted) connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node)) @@ -239,12 +205,12 @@ def run_test(self): # triggers a getdata on block 2 (it should if block 2 is missing). with mininode_lock: # Clear state so we can check the getdata request - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_message(msg_inv([CInv(2, blocks_h3[0].sha256)])) test_node.sync_with_ping() with mininode_lock: - getdata = test_node.last_getdata + getdata = test_node.last_message["getdata"] # Check that the getdata includes the right block assert_equal(getdata.inv[0].hash, blocks_h2f[0].sha256) diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py index 438ca0de0a42..ed7e3feee637 100755 --- a/test/functional/p2p-compactblocks.py +++ b/test/functional/p2p-compactblocks.py @@ -16,64 +16,31 @@ class TestNode(NodeConnCB): def __init__(self): super().__init__() self.last_sendcmpct = [] - self.last_headers = None - self.last_inv = None - self.last_cmpctblock = None self.block_announced = False - self.last_getdata = None - self.last_getheaders = None - self.last_getblocktxn = None - self.last_block = None - self.last_blocktxn = None # Store the hashes of blocks we've seen announced. # This is for synchronizing the p2p message traffic, # so we can eg wait until a particular block is announced. - self.set_announced_blockhashes = set() - self.connected = False - - def on_open(self, conn): - self.connected = True - - def on_close(self, conn): - self.connected = False + self.announced_blockhashes = set() def on_sendcmpct(self, conn, message): self.last_sendcmpct.append(message) - def on_block(self, conn, message): - self.last_block = message - def on_cmpctblock(self, conn, message): - self.last_cmpctblock = message self.block_announced = True - self.last_cmpctblock.header_and_shortids.header.calc_sha256() - self.set_announced_blockhashes.add(self.last_cmpctblock.header_and_shortids.header.sha256) + self.last_message["cmpctblock"].header_and_shortids.header.calc_sha256() + self.announced_blockhashes.add(self.last_message["cmpctblock"].header_and_shortids.header.sha256) def on_headers(self, conn, message): - self.last_headers = message self.block_announced = True - for x in self.last_headers.headers: + for x in self.last_message["headers"].headers: x.calc_sha256() - self.set_announced_blockhashes.add(x.sha256) + self.announced_blockhashes.add(x.sha256) def on_inv(self, conn, message): - self.last_inv = message - for x in self.last_inv.inv: + for x in self.last_message["inv"].inv: if x.type == 2: self.block_announced = True - self.set_announced_blockhashes.add(x.hash) - - def on_getdata(self, conn, message): - self.last_getdata = message - - def on_getheaders(self, conn, message): - self.last_getheaders = message - - def on_getblocktxn(self, conn, message): - self.last_getblocktxn = message - - def on_blocktxn(self, conn, message): - self.last_blocktxn = message + self.announced_blockhashes.add(x.hash) # Requires caller to hold mininode_lock def received_block_announcement(self): @@ -82,9 +49,9 @@ def received_block_announcement(self): def clear_block_announcement(self): with mininode_lock: self.block_announced = False - self.last_inv = None - self.last_headers = None - self.last_cmpctblock = None + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) + self.last_message.pop("cmpctblock", None) def get_headers(self, locator, hashstop): msg = msg_getheaders() @@ -100,15 +67,14 @@ def send_header_for_blocks(self, new_blocks): def request_headers_and_sync(self, locator, hashstop=0): self.clear_block_announcement() self.get_headers(locator, hashstop) - assert(wait_until(self.received_block_announcement, timeout=30)) - assert(self.received_block_announcement()) + assert wait_until(self.received_block_announcement, timeout=30) self.clear_block_announcement() # Block until a block announcement for a particular block hash is # received. def wait_for_block_announcement(self, block_hash, timeout=30): def received_hash(): - return (block_hash in self.set_announced_blockhashes) + return (block_hash in self.announced_blockhashes) return wait_until(received_hash, timeout=timeout) def send_await_disconnect(self, message, timeout=30): @@ -205,14 +171,14 @@ def check_announcement_of_new_block(node, peer, predicate): with mininode_lock: assert predicate(peer), ( "block_hash={!r}, cmpctblock={!r}, inv={!r}".format( - block_hash, peer.last_cmpctblock, peer.last_inv)) + block_hash, peer.last_message.get("cmpctblock", None), peer.last_message.get("inv", None))) # We shouldn't get any block announcements via cmpctblock yet. - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) # Try one more time, this time after requesting headers. test_node.request_headers_and_sync(locator=[tip]) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_inv is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "inv" in p.last_message) # Test a few ways of using sendcmpct that should NOT # result in compact block announcements. @@ -224,7 +190,7 @@ def check_announcement_of_new_block(node, peer, predicate): sendcmpct.version = preferred_version+1 sendcmpct.announce = True test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) # Headers sync before next test. test_node.request_headers_and_sync(locator=[tip]) @@ -233,7 +199,7 @@ def check_announcement_of_new_block(node, peer, predicate): sendcmpct.version = preferred_version sendcmpct.announce = False test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message) # Headers sync before next test. test_node.request_headers_and_sync(locator=[tip]) @@ -242,20 +208,20 @@ def check_announcement_of_new_block(node, peer, predicate): sendcmpct.version = preferred_version sendcmpct.announce = True test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) # Try one more time (no headers sync should be needed!) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) # Try one more time, after turning on sendheaders test_node.send_and_ping(msg_sendheaders()) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message) # Now turn off announcements sendcmpct.version = preferred_version sendcmpct.announce = False test_node.send_and_ping(sendcmpct) - check_announcement_of_new_block(node, test_node, lambda p: p.last_cmpctblock is None and p.last_headers is not None) + check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message and "headers" in p.last_message) # This code should be enabled after increasing cmctblk version #if old_node is not None: @@ -266,7 +232,7 @@ def check_announcement_of_new_block(node, peer, predicate): #old_node.send_and_ping(sendcmpct) # Header sync #old_node.request_headers_and_sync(locator=[tip]) - #check_announcement_of_new_block(node, old_node, lambda p: p.last_cmpctblock is not None) + #check_announcement_of_new_block(node, old_node, lambda p: "cmpctblock" in p.last_message) # This test actually causes bitcoind to (reasonably!) disconnect us, so do this last. def test_invalid_cmpctblock_message(self): @@ -318,9 +284,9 @@ def test_compactblock_construction(self, node, test_node, version): # Now fetch and check the compact block header_and_shortids = None with mininode_lock: - assert(test_node.last_cmpctblock is not None) + assert("cmpctblock" in test_node.last_message) # Convert the on-the-wire representation to absolute indexes - header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids) + header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids) self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) # Now fetch the compact block using a normal non-announce getdata @@ -335,9 +301,9 @@ def test_compactblock_construction(self, node, test_node, version): # Now fetch and check the compact block header_and_shortids = None with mininode_lock: - assert(test_node.last_cmpctblock is not None) + assert("cmpctblock" in test_node.last_message) # Convert the on-the-wire representation to absolute indexes - header_and_shortids = HeaderAndShortIDs(test_node.last_cmpctblock.header_and_shortids) + header_and_shortids = HeaderAndShortIDs(test_node.last_message["cmpctblock"].header_and_shortids) self.check_compactblock_construction_from_block(version, header_and_shortids, block_hash, block) def check_compactblock_construction_from_block(self, version, header_and_shortids, block_hash, block): @@ -384,20 +350,20 @@ def test_compactblock_requests(self, node, test_node): for announce in ["inv", "header"]: block = self.build_block_on_tip(node) with mininode_lock: - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) if announce == "inv": test_node.send_message(msg_inv([CInv(2, block.sha256)])) - success = wait_until(lambda: test_node.last_getheaders is not None, timeout=30) + success = wait_until(lambda: "getheaders" in test_node.last_message, timeout=30) assert(success) test_node.send_header_for_blocks([block]) else: test_node.send_header_for_blocks([block]) - success = wait_until(lambda: test_node.last_getdata is not None, timeout=30) + success = wait_until(lambda: "getdata" in test_node.last_message, timeout=30) assert(success) - assert_equal(len(test_node.last_getdata.inv), 1) - assert_equal(test_node.last_getdata.inv[0].type, 20) - assert_equal(test_node.last_getdata.inv[0].hash, block.sha256) + assert_equal(len(test_node.last_message["getdata"].inv), 1) + assert_equal(test_node.last_message["getdata"].inv[0].type, 20) + assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256) # Send back a compactblock message that omits the coinbase comp_block = HeaderAndShortIDs() @@ -410,8 +376,8 @@ def test_compactblock_requests(self, node, test_node): assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # Expect a getblocktxn message. with mininode_lock: - assert(test_node.last_getblocktxn is not None) - absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute() + assert("getblocktxn" in test_node.last_message) + absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, [0]) # should be a coinbase request # Send the coinbase, and verify that the tip advances. @@ -446,8 +412,8 @@ def test_getblocktxn_response(compact_block, peer, expected_result): msg = msg_cmpctblock(compact_block.to_p2p()) peer.send_and_ping(msg) with mininode_lock: - assert(peer.last_getblocktxn is not None) - absolute_indexes = peer.last_getblocktxn.block_txn_request.to_absolute() + assert("getblocktxn" in peer.last_message) + absolute_indexes = peer.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, expected_result) def test_tip_after_message(node, peer, msg, tip): @@ -509,14 +475,14 @@ def test_tip_after_message(node, peer, msg, tip): # Clear out last request. with mininode_lock: - test_node.last_getblocktxn = None + test_node.last_message.pop("getblocktxn", None) # Send compact block comp_block.initialize_from_block(block, prefill_list=[0]) test_tip_after_message(node, test_node, msg_cmpctblock(comp_block.to_p2p()), block.sha256) with mininode_lock: # Shouldn't have gotten a request for any transaction - assert(test_node.last_getblocktxn is None) + assert("getblocktxn" not in test_node.last_message) # Incorrectly responding to a getblocktxn shouldn't cause the block to be # permanently failed. @@ -542,8 +508,8 @@ def test_incorrect_blocktxn_response(self, node, test_node, version): test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p())) absolute_indexes = [] with mininode_lock: - assert(test_node.last_getblocktxn is not None) - absolute_indexes = test_node.last_getblocktxn.block_txn_request.to_absolute() + assert("getblocktxn" in test_node.last_message) + absolute_indexes = test_node.last_message["getblocktxn"].block_txn_request.to_absolute() assert_equal(absolute_indexes, [6, 7, 8, 9, 10]) # Now give an incorrect response. @@ -562,11 +528,11 @@ def test_incorrect_blocktxn_response(self, node, test_node, version): assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock) # We should receive a getdata request - success = wait_until(lambda: test_node.last_getdata is not None, timeout=10) + success = wait_until(lambda: "getdata" in test_node.last_message, timeout=10) assert(success) - assert_equal(len(test_node.last_getdata.inv), 1) - assert(test_node.last_getdata.inv[0].type == 2) - assert_equal(test_node.last_getdata.inv[0].hash, block.sha256) + assert_equal(len(test_node.last_message["getdata"].inv), 1) + assert(test_node.last_message["getdata"].inv[0].type == 2) + assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256) # Deliver the block test_node.send_and_ping(msg_block(block)) @@ -587,18 +553,18 @@ def test_getblocktxn_handler(self, node, test_node, version): num_to_request = random.randint(1, len(block.vtx)) msg.block_txn_request.from_absolute(sorted(random.sample(range(len(block.vtx)), num_to_request))) test_node.send_message(msg) - success = wait_until(lambda: test_node.last_blocktxn is not None, timeout=10) + success = wait_until(lambda: "blocktxn" in test_node.last_message, timeout=10) assert(success) [tx.calc_sha256() for tx in block.vtx] with mininode_lock: - assert_equal(test_node.last_blocktxn.block_transactions.blockhash, int(block_hash, 16)) + assert_equal(test_node.last_message["blocktxn"].block_transactions.blockhash, int(block_hash, 16)) all_indices = msg.block_txn_request.to_absolute() for index in all_indices: - tx = test_node.last_blocktxn.block_transactions.transactions.pop(0) + tx = test_node.last_message["blocktxn"].block_transactions.transactions.pop(0) tx.calc_sha256() assert_equal(tx.sha256, block.vtx[index].sha256) - test_node.last_blocktxn = None + test_node.last_message.pop("blocktxn", None) current_height -= 1 # Next request should send a full block response, as we're past the @@ -606,13 +572,13 @@ def test_getblocktxn_handler(self, node, test_node, version): block_hash = node.getblockhash(current_height) msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [0]) with mininode_lock: - test_node.last_block = None - test_node.last_blocktxn = None + test_node.last_message.pop("block", None) + test_node.last_message.pop("blocktxn", None) test_node.send_and_ping(msg) with mininode_lock: - test_node.last_block.block.calc_sha256() - assert_equal(test_node.last_block.block.sha256, int(block_hash, 16)) - assert_equal(test_node.last_blocktxn, None) + test_node.last_message["block"].block.calc_sha256() + assert_equal(test_node.last_message["block"].block.sha256, int(block_hash, 16)) + assert "blocktxn" not in test_node.last_message def test_compactblocks_not_at_tip(self, node, test_node): # Test that requesting old compactblocks doesn't work. @@ -625,7 +591,7 @@ def test_compactblocks_not_at_tip(self, node, test_node): test_node.clear_block_announcement() test_node.send_message(msg_getdata([CInv(20, int(new_blocks[0], 16))])) - success = wait_until(lambda: test_node.last_cmpctblock is not None, timeout=30) + success = wait_until(lambda: "cmpctblock" in test_node.last_message, timeout=30) assert(success) test_node.clear_block_announcement() @@ -633,13 +599,13 @@ def test_compactblocks_not_at_tip(self, node, test_node): wait_until(test_node.received_block_announcement, timeout=30) test_node.clear_block_announcement() with mininode_lock: - test_node.last_block = None + test_node.last_message.pop("block", None) test_node.send_message(msg_getdata([CInv(20, int(new_blocks[0], 16))])) - success = wait_until(lambda: test_node.last_block is not None, timeout=30) + success = wait_until(lambda: "block" in test_node.last_message, timeout=30) assert(success) with mininode_lock: - test_node.last_block.block.calc_sha256() - assert_equal(test_node.last_block.block.sha256, int(new_blocks[0], 16)) + test_node.last_message["block"].block.calc_sha256() + assert_equal(test_node.last_message["block"].block.sha256, int(new_blocks[0], 16)) # Generate an old compactblock, and verify that it's not accepted. cur_height = node.getblockcount() @@ -666,10 +632,10 @@ def test_compactblocks_not_at_tip(self, node, test_node): msg = msg_getblocktxn() msg.block_txn_request = BlockTransactionsRequest(block.sha256, [0]) with mininode_lock: - test_node.last_blocktxn = None + test_node.last_message.pop("blocktxn", None) test_node.send_and_ping(msg) with mininode_lock: - assert(test_node.last_blocktxn is None) + assert "blocktxn" not in test_node.last_message def test_end_to_end_block_relay(self, node, listeners): utxo = self.utxos.pop(0) @@ -684,9 +650,9 @@ def test_end_to_end_block_relay(self, node, listeners): wait_until(lambda: l.received_block_announcement(), timeout=30) with mininode_lock: for l in listeners: - assert(l.last_cmpctblock is not None) - l.last_cmpctblock.header_and_shortids.header.calc_sha256() - assert_equal(l.last_cmpctblock.header_and_shortids.header.sha256, block.sha256) + assert "cmpctblock" in l.last_message + l.last_message["cmpctblock"].header_and_shortids.header.calc_sha256() + assert_equal(l.last_message["cmpctblock"].header_and_shortids.header.sha256, block.sha256) # Test that we don't get disconnected if we relay a compact block with valid header, # but invalid transactions. @@ -733,7 +699,7 @@ def announce_cmpct_block(node, peer): msg = msg_cmpctblock(cmpct_block.to_p2p()) peer.send_and_ping(msg) with mininode_lock: - assert(peer.last_getblocktxn is not None) + assert "getblocktxn" in peer.last_message return block, cmpct_block block, cmpct_block = announce_cmpct_block(node, stalling_peer) diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p-leaktests.py index 205ec86a4c43..7c20614b18fe 100755 --- a/test/functional/p2p-leaktests.py +++ b/test/functional/p2p-leaktests.py @@ -20,15 +20,8 @@ class CLazyNode(NodeConnCB): def __init__(self): super().__init__() - self.connection = None self.unexpected_msg = False - self.connected = False - - def add_connection(self, conn): - self.connection = conn - - def send_message(self, message): - self.connection.send_message(message) + self.ever_connected = False def bad_message(self, message): self.unexpected_msg = True @@ -36,6 +29,7 @@ def bad_message(self, message): def on_open(self, conn): self.connected = True + self.ever_connected = True def on_version(self, conn, message): self.bad_message(message) def on_verack(self, conn, message): self.bad_message(message) @@ -62,9 +56,6 @@ def on_blocktxn(self, conn, message): self.bad_message(message) # Node that never sends a version. We'll use this to send a bunch of messages # anyway, and eventually get disconnected. class CNodeNoVersionBan(CLazyNode): - def __init__(self): - super().__init__() - # send a bunch of veracks without sending a message. This should get us disconnected. # NOTE: implementation-specific check here. Remove if bitcoind ban behavior changes def on_open(self, conn): @@ -120,7 +111,9 @@ def run_test(self): NetworkThread().start() # Start up network handling in another thread - assert(wait_until(lambda: no_version_bannode.connected and no_version_idlenode.connected and no_verack_idlenode.version_received, timeout=10)) + assert wait_until(lambda: no_version_bannode.ever_connected, timeout=10) + assert wait_until(lambda: no_version_idlenode.ever_connected, timeout=10) + assert wait_until(lambda: no_verack_idlenode.version_received, timeout=10) # Mine a block and make sure that it's not sent to the connected nodes self.nodes[0].generate(1) @@ -129,7 +122,7 @@ def run_test(self): time.sleep(5) #This node should have been banned - assert(no_version_bannode.connection.state == "closed") + assert not no_version_bannode.connected [conn.disconnect_node() for conn in connections] diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p-mempool.py index 5064ce74aab0..188016e7184c 100755 --- a/test/functional/p2p-mempool.py +++ b/test/functional/p2p-mempool.py @@ -12,60 +12,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -class TestNode(NodeConnCB): - def __init__(self): - super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() - self.block_receive_map = {} - - def add_connection(self, conn): - self.connection = conn - self.peer_disconnected = False - - def on_inv(self, conn, message): - pass - - # Track the last getdata message we receive (used in the test) - def on_getdata(self, conn, message): - self.last_getdata = message - - def on_block(self, conn, message): - message.block.calc_sha256() - try: - self.block_receive_map[message.block.sha256] += 1 - except KeyError as e: - self.block_receive_map[message.block.sha256] = 1 - - # Spin until verack message is received from the node. - # We use this to signal that our test can begin. This - # is called from the testing thread, so it needs to acquire - # the global lock. - def wait_for_verack(self): - def veracked(): - return self.verack_received - return wait_until(veracked, timeout=10) - - def wait_for_disconnect(self): - def disconnected(): - return self.peer_disconnected - return wait_until(disconnected, timeout=10) - - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_pong(self, conn, message): - self.last_pong = message - - def on_close(self, conn): - self.peer_disconnected = True - - def send_mempool(self): - self.lastInv = [] - self.send_message(msg_mempool()) - class P2PMempoolTests(BitcoinTestFramework): def __init__(self): @@ -74,20 +20,18 @@ def __init__(self): self.num_nodes = 2 def setup_network(self): - # Start a node with maxuploadtarget of 200 MB (/24h) - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-peerbloomfilters=0"])) + self.nodes = [start_node(0, self.options.tmpdir, ["-peerbloomfilters=0"])] def run_test(self): #connect a mininode - aTestNode = TestNode() + aTestNode = NodeConnCB() node = NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], aTestNode) aTestNode.add_connection(node) NetworkThread().start() aTestNode.wait_for_verack() #request mempool - aTestNode.send_mempool() + aTestNode.send_message(msg_mempool()) aTestNode.wait_for_disconnect() #mininode must be disconnected at this point diff --git a/test/functional/p2p-timeouts.py b/test/functional/p2p-timeouts.py index de4edd6800c9..210e561e7436 100755 --- a/test/functional/p2p-timeouts.py +++ b/test/functional/p2p-timeouts.py @@ -28,20 +28,9 @@ from test_framework.util import * class TestNode(NodeConnCB): - def __init__(self): - super().__init__() - self.connected = False - self.received_version = False - - def on_open(self, conn): - self.connected = True - - def on_close(self, conn): - self.connected = False - def on_version(self, conn, message): # Don't send a verack in response - self.received_version = True + pass class TimeoutsTest(BitcoinTestFramework): def __init__(self): @@ -83,7 +72,7 @@ def run_test(self): sleep(30) - assert(self.no_verack_node.received_version) + assert "version" in self.no_verack_node.last_message assert(self.no_verack_node.connected) assert(self.no_version_node.connected) diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py index da960e2d804c..06cdd5f91d11 100755 --- a/test/functional/p2p-versionbits-warning.py +++ b/test/functional/p2p-versionbits-warning.py @@ -24,28 +24,10 @@ WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT) VB_PATTERN = re.compile("^Warning.*versionbit") -# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending -# p2p messages to a node, generating the messages in the main testing logic. class TestNode(NodeConnCB): - def __init__(self): - super().__init__() - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() - - def add_connection(self, conn): - self.connection = conn - def on_inv(self, conn, message): pass - # Wrapper for the NodeConn's send_message function - def send_message(self, message): - self.connection.send_message(message) - - def on_pong(self, conn, message): - self.last_pong = message - class VersionBitsWarningTest(BitcoinTestFramework): def __init__(self): super().__init__() diff --git a/test/functional/sendheaders.py b/test/functional/sendheaders.py index 49266da5f1c7..72cddb91ccaa 100755 --- a/test/functional/sendheaders.py +++ b/test/functional/sendheaders.py @@ -92,23 +92,17 @@ direct_fetch_response_time = 0.05 -class BaseNode(NodeConnCB): +class TestNode(NodeConnCB): def __init__(self): super().__init__() - self.last_inv = None - self.last_headers = None - self.last_block = None - self.last_getdata = None self.block_announced = False - self.last_getheaders = None - self.disconnected = False self.last_blockhash_announced = None def clear_last_announcement(self): with mininode_lock: self.block_announced = False - self.last_inv = None - self.last_headers = None + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) # Request data for a list of block hashes def get_data(self, block_hashes): @@ -129,29 +123,17 @@ def send_block_inv(self, blockhash): self.connection.send_message(msg) def on_inv(self, conn, message): - self.last_inv = message self.block_announced = True self.last_blockhash_announced = message.inv[-1].hash def on_headers(self, conn, message): - self.last_headers = message if len(message.headers): self.block_announced = True message.headers[-1].calc_sha256() self.last_blockhash_announced = message.headers[-1].sha256 def on_block(self, conn, message): - self.last_block = message.block - self.last_block.calc_sha256() - - def on_getdata(self, conn, message): - self.last_getdata = message - - def on_getheaders(self, conn, message): - self.last_getheaders = message - - def on_close(self, conn): - self.disconnected = True + self.last_message["block"].calc_sha256() # Test whether the last announcement we received had the # right header or the right inv @@ -166,43 +148,27 @@ def check_last_announcement(self, headers=None, inv=None): success = True compare_inv = [] - if self.last_inv != None: - compare_inv = [x.hash for x in self.last_inv.inv] + if "inv" in self.last_message: + compare_inv = [x.hash for x in self.last_message["inv"].inv] if compare_inv != expect_inv: success = False hash_headers = [] - if self.last_headers != None: + if "headers" in self.last_message: # treat headers as a list of block hashes - hash_headers = [ x.sha256 for x in self.last_headers.headers ] + hash_headers = [ x.sha256 for x in self.last_message["headers"].headers ] if hash_headers != expect_headers: success = False - self.last_inv = None - self.last_headers = None + self.last_message.pop("inv", None) + self.last_message.pop("headers", None) return success - # Syncing helpers - def wait_for_block(self, blockhash, timeout=60): - test_function = lambda: self.last_block != None and self.last_block.sha256 == blockhash - assert(wait_until(test_function, timeout=timeout)) - return - - def wait_for_getheaders(self, timeout=60): - test_function = lambda: self.last_getheaders != None - assert(wait_until(test_function, timeout=timeout)) - return - def wait_for_getdata(self, hash_list, timeout=60): if hash_list == []: return - test_function = lambda: self.last_getdata != None and [x.hash for x in self.last_getdata.inv] == hash_list - assert(wait_until(test_function, timeout=timeout)) - return - - def wait_for_disconnect(self, timeout=60): - test_function = lambda: self.disconnected + test_function = lambda: "getdata" in self.last_message and [x.hash for x in self.last_message["getdata"].inv] == hash_list assert(wait_until(test_function, timeout=timeout)) return @@ -221,17 +187,6 @@ def send_getblocks(self, locator): getblocks_message.locator.vHave = locator self.send_message(getblocks_message) -# InvNode: This peer should only ever receive inv's, because it doesn't ever send a -# "sendheaders" message. -class InvNode(BaseNode): - def __init__(self): - BaseNode.__init__(self) - -# TestNode: This peer is the one we use for most of the testing. -class TestNode(BaseNode): - def __init__(self): - BaseNode.__init__(self) - class SendHeadersTest(BitcoinTestFramework): def __init__(self): super().__init__() @@ -271,7 +226,7 @@ def mine_reorg(self, length): def run_test(self): # Setup the p2p connections and start up the network thread. - inv_node = InvNode() + inv_node = TestNode() test_node = TestNode() self.p2p_connections = [inv_node, test_node] @@ -407,8 +362,8 @@ def test_nonnull_locators(self, test_node, inv_node): inv_node.sync_with_ping() # This block should not be announced to the inv node (since it also # broadcast it) - assert_equal(inv_node.last_inv, None) - assert_equal(inv_node.last_headers, None) + assert "inv" not in inv_node.last_message + assert "headers" not in inv_node.last_message tip = self.mine_blocks(1) assert_equal(inv_node.check_last_announcement(inv=[tip]), True) assert_equal(test_node.check_last_announcement(headers=[tip]), True) @@ -498,12 +453,12 @@ def test_nonnull_locators(self, test_node, inv_node): inv_node.send_message(msg_block(blocks[-1])) inv_node.sync_with_ping() # Make sure blocks are processed - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks) test_node.sync_with_ping() # should not have received any getdata messages with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message # This time, direct fetch should work blocks = [] @@ -537,11 +492,11 @@ def test_nonnull_locators(self, test_node, inv_node): # Announcing one block on fork should not trigger direct fetch # (less work than tip) - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks[0:1]) test_node.sync_with_ping() with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message # Announcing one more block on fork should trigger direct fetch for # both blocks (same work as tip) @@ -556,11 +511,11 @@ def test_nonnull_locators(self, test_node, inv_node): test_node.wait_for_getdata([x.sha256 for x in blocks[2:16]], timeout=direct_fetch_response_time) # Announcing 1 more header should not trigger any response - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) test_node.send_header_for_blocks(blocks[18:19]) test_node.sync_with_ping() with mininode_lock: - assert_equal(test_node.last_getdata, None) + assert "getdata" not in test_node.last_message self.log.info("Part 4: success!") @@ -571,7 +526,7 @@ def test_nonnull_locators(self, test_node, inv_node): # First we test that receipt of an unconnecting header doesn't prevent # chain sync. for i in range(10): - test_node.last_getdata = None + test_node.last_message.pop("getdata", None) blocks = [] # Create two more blocks. for j in range(2): @@ -582,7 +537,7 @@ def test_nonnull_locators(self, test_node, inv_node): height += 1 # Send the header of the second block -> this won't connect. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[1]]) test_node.wait_for_getheaders() test_node.send_header_for_blocks(blocks) @@ -605,7 +560,7 @@ def test_nonnull_locators(self, test_node, inv_node): for i in range(1, MAX_UNCONNECTING_HEADERS): # Send a header that doesn't connect, check that we get a getheaders. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[i]]) test_node.wait_for_getheaders() @@ -620,25 +575,21 @@ def test_nonnull_locators(self, test_node, inv_node): for i in range(5*MAX_UNCONNECTING_HEADERS - 1): # Send a header that doesn't connect, check that we get a getheaders. with mininode_lock: - test_node.last_getheaders = None + test_node.last_message.pop("getheaders", None) test_node.send_header_for_blocks([blocks[i%len(blocks)]]) test_node.wait_for_getheaders() # Eventually this stops working. - with mininode_lock: - self.last_getheaders = None test_node.send_header_for_blocks([blocks[-1]]) # Should get disconnected test_node.wait_for_disconnect() - with mininode_lock: - self.last_getheaders = True self.log.info("Part 5: success!") # Finally, check that the inv node never received a getdata request, # throughout the test - assert_equal(inv_node.last_getdata, None) + assert "getdata" not in inv_node.last_message if __name__ == '__main__': SendHeadersTest().main() diff --git a/test/functional/test_framework/comptool.py b/test/functional/test_framework/comptool.py index f5c19001332b..7ad894e9017e 100755 --- a/test/functional/test_framework/comptool.py +++ b/test/functional/test_framework/comptool.py @@ -192,9 +192,7 @@ def disconnected(): return wait_until(disconnected, timeout=10) def wait_for_verack(self): - def veracked(): - return all(node.verack_received for node in self.test_nodes) - return wait_until(veracked, timeout=10) + return all(node.wait_for_verack() for node in self.test_nodes) def wait_for_pings(self, counter, timeout=float('inf')): def received_pongs(): diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index b80bca2a0d8a..bcc7db8bb759 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -20,23 +20,24 @@ ser_*, deser_*: functions that handle serialization/deserialization """ -import struct -import socket import asyncore from collections import namedtuple -import time -import sys -import random -from .util import hex_str_to_bytes, bytes_to_hex_str -from io import BytesIO from codecs import encode +from collections import defaultdict +import copy import hashlib -from threading import RLock -from threading import Thread +from io import BytesIO import logging -import copy +import random +import socket +import struct +import sys +import time +from threading import RLock, Thread + from test_framework.siphash import siphash256 +from test_framework.util import hex_str_to_bytes, bytes_to_hex_str import dash_hash @@ -1595,30 +1596,57 @@ def __repr__(self): return "msg_islock(inputs=%s, txid=%064x)" % (repr(self.inputs), self.txid) -# This is what a callback should look like for NodeConn -# Reimplement the on_* functions to provide handling for events class NodeConnCB(object): + """Callback and helper functions for P2P connection to a bitcoind node. + + Individual testcases should subclass this and override the on_* methods + if they want to alter message handling behaviour. + """ + def __init__(self): - self.verack_received = False + # Track whether we have a P2P connection open to the node + self.connected = False + self.connection = None + + # Track number of messages of each type received and the most recent + # message of each type + self.message_count = defaultdict(int) + self.last_message = {} + + # A count of the number of ping messages we've sent to the node + self.ping_counter = 1 + # deliver_sleep_time is helpful for debugging race conditions in p2p # tests; it causes message delivery to sleep for the specified time # before acquiring the global lock and delivering the next message. self.deliver_sleep_time = None + # Remember the services our peer has advertised self.peer_services = None - self.connection = None - self.ping_counter = 1 - self.last_pong = msg_pong() + + # Message receiving methods def deliver(self, conn, message): + """Receive message and dispatch message to appropriate callback. + + We keep a count of how many of each message type has been received + and the most recent message of each type. + + Optionally waits for deliver_sleep_time before dispatching message. + """ + deliver_sleep = self.get_deliver_sleep_time() if deliver_sleep is not None: time.sleep(deliver_sleep) with mininode_lock: try: - getattr(self, 'on_' + message.command.decode('ascii'))(conn, message) + command = message.command.decode('ascii') + self.message_count[command] += 1 + self.last_message[command] = message + getattr(self, 'on_' + command)(conn, message) except: - logger.exception("ERROR delivering %s" % repr(message)) + print("ERROR delivering %s (%s)" % (repr(message), + sys.exc_info()[0])) def set_deliver_sleep_time(self, value): with mininode_lock: @@ -1628,14 +1656,20 @@ def get_deliver_sleep_time(self): with mininode_lock: return self.deliver_sleep_time - # Callbacks which can be overridden by subclasses - ################################################# + # Callback methods. Can be overridden by subclasses in individual test + # cases to provide custom message handling behaviour. + + def on_open(self, conn): + self.connected = True + + def on_close(self, conn): + self.connected = False + self.connection = None def on_addr(self, conn, message): pass def on_alert(self, conn, message): pass def on_block(self, conn, message): pass def on_blocktxn(self, conn, message): pass - def on_close(self, conn): pass def on_cmpctblock(self, conn, message): pass def on_feefilter(self, conn, message): pass def on_getaddr(self, conn, message): pass @@ -1645,7 +1679,7 @@ def on_getdata(self, conn, message): pass def on_getheaders(self, conn, message): pass def on_headers(self, conn, message): pass def on_mempool(self, conn): pass - def on_open(self, conn): pass + def on_pong(self, conn, message): pass def on_reject(self, conn, message): pass def on_sendcmpct(self, conn, message): pass def on_sendheaders(self, conn, message): pass @@ -1663,9 +1697,6 @@ def on_ping(self, conn, message): if conn.ver_send > BIP0031_VERSION: conn.send_message(msg_pong(message.nonce)) - def on_pong(self, conn, message): - self.last_pong = message - def on_mnlistdiff(self, conn, message): pass def on_clsig(self, conn, message): pass def on_islock(self, conn, message): pass @@ -1682,15 +1713,44 @@ def on_version(self, conn, message): conn.ver_recv = conn.ver_send conn.nServices = message.nServices - # Helper functions - ################## + # Connection helper methods def add_connection(self, conn): self.connection = conn - # Wrapper for the NodeConn's send_message function + def wait_for_disconnect(self, timeout=60): + test_function = lambda: not self.connected + assert wait_until(test_function, timeout=timeout) + + # Message receiving helper methods + + def wait_for_block(self, blockhash, timeout=60): + test_function = lambda: self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash + assert wait_until(test_function, timeout=timeout) + + def wait_for_getdata(self, timeout=60): + test_function = lambda: self.last_message.get("getdata") + assert wait_until(test_function, timeout=timeout) + + def wait_for_getheaders(self, timeout=60): + test_function = lambda: self.last_message.get("getheaders") + assert wait_until(test_function, timeout=timeout) + + def wait_for_inv(self, expected_inv, timeout=60): + test_function = lambda: self.last_message.get("inv") and self.last_message["inv"] != expected_inv + assert wait_until(test_function, timeout=timeout) + + def wait_for_verack(self, timeout=60): + test_function = lambda: self.message_count["verack"] + assert wait_until(test_function, timeout=timeout) + + # Message sending helper functions + def send_message(self, message): - self.connection.send_message(message) + if self.connection: + self.connection.send_message(message) + else: + logger.error("Cannot send message. No connection to node!") def send_and_ping(self, message): self.send_message(message) @@ -1698,27 +1758,11 @@ def send_and_ping(self, message): # Sync up with the node def sync_with_ping(self, timeout=60): - def received_pong(): - return (self.last_pong.nonce == self.ping_counter) self.send_message(msg_ping(nonce=self.ping_counter)) - success = wait_until(received_pong, timeout=timeout) - if not success: - logger.error("sync_with_ping failed!") - raise AssertionError("sync_with_ping failed!") + test_function = lambda: self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter + assert wait_until(test_function, timeout=timeout) self.ping_counter += 1 - - return success - - # Spin until verack message is received from the node. - # Tests may want to use this as a signal that the test can begin. - # This can be called from the testing thread, so it needs to acquire the - # global lock. - def wait_for_verack(self): - while True: - with mininode_lock: - if self.verack_received: - return - time.sleep(0.05) + return True # The actual NodeConn class # This class provides an interface for a p2p connection to a specified node From 05139e3eb414cf553f615ee59f5b2368500cd884 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 10 Jun 2019 00:47:09 -0500 Subject: [PATCH 183/987] remove MyNodeConnCB Class and references Signed-off-by: Pasta --- test/functional/p2p-fingerprint.py | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/test/functional/p2p-fingerprint.py b/test/functional/p2p-fingerprint.py index 6c43cb95d6f8..617c6c150c67 100755 --- a/test/functional/p2p-fingerprint.py +++ b/test/functional/p2p-fingerprint.py @@ -89,26 +89,7 @@ def last_header_equals(self, expected_hash, node): # This does not currently test that stale blocks timestamped within the # last month but that have over a month's worth of work are also withheld. def run_test(self): - # TODO remove this when mininode is up-to-date with Bitcoin - class MyNodeConnCB(NodeConnCB): - def __init__(self): - super().__init__() - self.cond = threading.Condition() - self.last_message = {} - - def deliver(self, conn, message): - super().deliver(conn, message) - command = message.command.decode('ascii') - self.last_message[command] = message - with self.cond: - self.cond.notify_all() - - def wait_for_getdata(self): - with self.cond: - assert(self.cond.wait_for(lambda: "getdata" in self.last_message, timeout=15)) - - - node0 = MyNodeConnCB() + node0 = NodeConnCB() connections = [] connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0)) From 4daceb9feea4db2de5e8fb68768daef4d69d19fb Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 23 Apr 2017 17:04:38 +0200 Subject: [PATCH 184/987] Merge #10224: [test] Add test for getaddednodeinfo bc53752 Tests: Add simple test for getaddednodeinfo (Jimmy Song) Tree-SHA512: d2f8a384fb994b83f881b585db70e7cf57980821074126d254960cb67988a40672ffde065d0ccd9a90f9e3b395d8cd33695c796ecb4b54f69fe74ee2bf7497a6 --- test/functional/net.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/test/functional/net.py b/test/functional/net.py index e9463c7dc7df..a82cdabf524c 100755 --- a/test/functional/net.py +++ b/test/functional/net.py @@ -7,15 +7,15 @@ Tests correspond to code in rpc/net.cpp. """ -from decimal import Decimal import time from test_framework.test_framework import BitcoinTestFramework -from test_framework.authproxy import JSONRPCException from test_framework.util import ( assert_equal, - start_nodes, + assert_raises_jsonrpc, connect_nodes_bi, + p2p_port, + start_nodes, ) @@ -33,7 +33,7 @@ def setup_network(self): def run_test(self): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) - assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) # bilateral connection + assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) self.nodes[0].setnetworkactive(False) assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], False) @@ -49,6 +49,19 @@ def run_test(self): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) + # test getaddednodeinfo + assert_equal(self.nodes[0].getaddednodeinfo(), []) + # add a node (node2) to node0 + ip_port = "127.0.0.1:{}".format(p2p_port(2)) + self.nodes[0].addnode(ip_port, 'add') + # check that the node has indeed been added + added_nodes = self.nodes[0].getaddednodeinfo(ip_port) + assert_equal(len(added_nodes), 1) + assert_equal(added_nodes[0]['addednode'], ip_port) + # check that a non-existant node returns an error + assert_raises_jsonrpc(-24, "Node has not been added", + self.nodes[0].getaddednodeinfo, '1.1.1.1') + if __name__ == '__main__': NetTest().main() From dfabead29c6afb9fc0cd9d4eaa92cea69afe49c5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 1 May 2017 12:14:20 +0200 Subject: [PATCH 185/987] Merge #10264: [test] Add tests for getconnectioncount, getnettotals and ping 85f950a [test] Add tests for getconnectioncount, getnettotals and ping (Jimmy Song) Tree-SHA512: f9cccc749cd897a4e90400173d63da27798fe606ede216bdcfcce73848370327e010fa7ae70bd2974b24b3e688337e2ad18f0959ffed57cae9c0803456bab09a --- test/functional/net.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/test/functional/net.py b/test/functional/net.py index a82cdabf524c..9eae14045502 100755 --- a/test/functional/net.py +++ b/test/functional/net.py @@ -32,6 +32,39 @@ def setup_network(self): self.sync_all() def run_test(self): + self._test_connection_count() + self._test_getnettotals() + self._test_getnetworkinginfo() + self._test_getaddednodeinfo() + + def _test_connection_count(self): + # connect_nodes_bi connects each node to the other + assert_equal(self.nodes[0].getconnectioncount(), 2) + + def _test_getnettotals(self): + # check that getnettotals totalbytesrecv and totalbytessent + # are consistent with getpeerinfo + peer_info = self.nodes[0].getpeerinfo() + assert_equal(len(peer_info), 2) + net_totals = self.nodes[0].getnettotals() + assert_equal(sum([peer['bytesrecv'] for peer in peer_info]), + net_totals['totalbytesrecv']) + assert_equal(sum([peer['bytessent'] for peer in peer_info]), + net_totals['totalbytessent']) + # test getnettotals and getpeerinfo by doing a ping + # the bytes sent/received should change + # note ping and pong are 32 bytes each + self.nodes[0].ping() + time.sleep(0.1) + peer_info_after_ping = self.nodes[0].getpeerinfo() + net_totals_after_ping = self.nodes[0].getnettotals() + for before, after in zip(peer_info, peer_info_after_ping): + assert_equal(before['bytesrecv_per_msg']['pong'] + 32, after['bytesrecv_per_msg']['pong']) + assert_equal(before['bytessent_per_msg']['ping'] + 32, after['bytessent_per_msg']['ping']) + assert_equal(net_totals['totalbytesrecv'] + 32*2, net_totals_after_ping['totalbytesrecv']) + assert_equal(net_totals['totalbytessent'] + 32*2, net_totals_after_ping['totalbytessent']) + + def _test_getnetworkinginfo(self): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) @@ -49,7 +82,7 @@ def run_test(self): assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True) assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2) - # test getaddednodeinfo + def _test_getaddednodeinfo(self): assert_equal(self.nodes[0].getaddednodeinfo(), []) # add a node (node2) to node0 ip_port = "127.0.0.1:{}".format(p2p_port(2)) From 5152e751cca7b7d3a8e14d2e6fbdcd1123fce9cc Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 14 Jun 2019 19:12:21 +0300 Subject: [PATCH 186/987] Notify UI/external scripts about wallet txes locks --- src/instantsend.cpp | 9 --------- src/llmq/quorums_instantsend.cpp | 13 ------------- src/wallet/wallet.cpp | 10 +++++++++- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/instantsend.cpp b/src/instantsend.cpp index 30ad074b550e..388681e81d6e 100644 --- a/src/instantsend.cpp +++ b/src/instantsend.cpp @@ -528,15 +528,6 @@ void CInstantSend::UpdateLockedTransaction(const CTxLockCandidate& txLockCandida if (!IsLockedInstantSendTransaction(txHash)) return; // not a locked tx, do not update/notify -#ifdef ENABLE_WALLET - // notify an external script once threshold is reached - std::string strCmd = GetArg("-instantsendnotify", ""); - if (!strCmd.empty()) { - boost::replace_all(strCmd, "%s", txHash.GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free - } -#endif - llmq::CInstantSendLock islock; GetMainSignals().NotifyTransactionLock(*txLockCandidate.txLockRequest.tx, islock); diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index c837b6fc8864..131c8c052739 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -929,19 +929,6 @@ void CInstantSendManager::UpdateWalletTransaction(const CTransactionRef& tx, con return; } -#ifdef ENABLE_WALLET - if (!pwalletMain) { - return; - } - - // notify an external script once threshold is reached - std::string strCmd = GetArg("-instantsendnotify", ""); - if (!strCmd.empty()) { - boost::replace_all(strCmd, "%s", tx->GetHash().GetHex()); - boost::thread t(runCommand, strCmd); // thread runs free - } -#endif - GetMainSignals().NotifyTransactionLock(*tx, islock); // bump mempool counter to make sure newly mined txes are picked up by getblocktemplate mempool.AddTransactionsUpdated(1); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 88558fbc51f7..0436fd2bef5d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5290,9 +5290,17 @@ void CWallet::NotifyTransactionLock(const CTransaction &tx, const llmq::CInstant { LOCK(cs_wallet); // Only notify UI if this transaction is in this wallet - std::map::const_iterator mi = mapWallet.find(tx.GetHash()); + uint256 txHash = tx.GetHash(); + std::map::const_iterator mi = mapWallet.find(txHash); if (mi != mapWallet.end()){ + NotifyTransactionChanged(this, txHash, CT_UPDATED); NotifyISLockReceived(); + // notify an external script + std::string strCmd = GetArg("-instantsendnotify", ""); + if (!strCmd.empty()) { + boost::replace_all(strCmd, "%s", txHash.GetHex()); + boost::thread t(runCommand, strCmd); // thread runs free + } } } From 4c7b47e2822ea009f8b02190f5bd4a8cb70ea6e1 Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 14 Jun 2019 23:37:44 -0500 Subject: [PATCH 187/987] Resolve comment, add check for fUseInstantSend and set value equal to the max value Signed-off-by: Pasta --- src/wallet/wallet.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0436fd2bef5d..27321c076cc1 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2698,6 +2698,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin std::vector vValue; CAmount nTotalLower = 0; + if (fUseInstantSend) { + coinLowestLarger->txout.nValue = sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE) * COIN; + } + random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); int tryDenomStart = 0; From 74830ee2a858139f3574451fe7fb0745a1b446a1 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 17 Jun 2019 20:01:47 -0500 Subject: [PATCH 188/987] adjust spork5 code in wallet.cpp Signed-off-by: Pasta --- src/wallet/wallet.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 27321c076cc1..527159b3885d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2698,8 +2698,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin std::vector vValue; CAmount nTotalLower = 0; - if (fUseInstantSend) { - coinLowestLarger->txout.nValue = sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE) * COIN; + // TODO: drop SPORK_5_INSTANTSEND_MAX_VALUE spork + if (fUseInstantSend && nTargetValue > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE) * COIN) { + return false; } random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); From a651f0d0fc7841b45239763ae5e9c50a395afece Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 17 Jun 2019 20:03:06 -0500 Subject: [PATCH 189/987] adjust test_runner.py check if dashd is running Signed-off-by: Pasta --- test/functional/test_runner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index a21fa30e788b..1085986fb2df 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -228,7 +228,8 @@ def main(): def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=False, args=[]): # Warn if dashd is already running (unix only) try: - if subprocess.check_output(["pidof", "dashd"]) is not None: + pidof_output = subprocess.check_output(["pidof", "dashd"]) + if not (pidof_output is None or pidof_output == b''): print("%sWARNING!%s There is already a dashd process running on this system. Tests may fail unexpectedly due to resource contention!" % (BOLD[1], BOLD[0])) except (OSError, subprocess.SubprocessError): pass From 98f3e295cc0288adbdd58fe465455c97d0cf6d63 Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 18 Jun 2019 00:47:25 -0500 Subject: [PATCH 190/987] add `&& llmq::IsOldInstantSendEnabled()` to instantsend max value check Signed-off-by: Pasta --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 527159b3885d..6856c45dc7fa 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2699,7 +2699,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin CAmount nTotalLower = 0; // TODO: drop SPORK_5_INSTANTSEND_MAX_VALUE spork - if (fUseInstantSend && nTargetValue > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE) * COIN) { + if (fUseInstantSend && nTargetValue > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE) * COIN && llmq::IsOldInstantSendEnabled()) { return false; } From 9c863edd9c66012c2500c60beca45abfe72f4f6d Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 28 Mar 2017 11:24:14 +0200 Subject: [PATCH 191/987] Merge #9780: Suppress noisy output from qa tests in Travis 8c7288c Print out the final 1000 lines of test_framework.log if test fails (John Newbery) 6d780b1 Update travis config to run rpc-tests.py in quiet mode (John Newbery) 55992f1 Add --quiet option to suppress rpc-tests.py output (John Newbery) Tree-SHA512: ab080458a07a9346d3b3cbc8ab59b73cea3d4010b1cb0206bb5fade0aaac7562c623475d0a02993f001b22ae9d1ba68e2d0d1a3645cea7e79cc1045b42e2ce3a --- .../test_framework/test_framework.py | 16 +++++++++---- test/functional/test_runner.py | 24 +++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 56e42f289c89..82d69b10162c 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -4,6 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Base class for RPC testing.""" +from collections import deque import logging import optparse import os @@ -196,12 +197,17 @@ def main(self): # Dump the end of the debug logs, to aid in debugging rare # travis failures. import glob - filenames = glob.glob(self.options.tmpdir + "/node*/regtest/debug.log") + filenames = [self.options.tmpdir + "/test_framework.log"] + filenames += glob.glob(self.options.tmpdir + "/node*/regtest/debug.log") MAX_LINES_TO_PRINT = 1000 - for f in filenames: - print("From" , f, ":") - from collections import deque - print("".join(deque(open(f), MAX_LINES_TO_PRINT))) + for fn in filenames: + try: + with open(fn, 'r') as f: + print("From" , fn, ":") + print("".join(deque(f, MAX_LINES_TO_PRINT))) + except OSError: + print("Opening file %s failed." % fn) + traceback.print_exc() if success: self.log.info("Tests successful") sys.exit(self.TEST_EXIT_PASSED) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 1085986fb2df..28b69b951946 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -23,6 +23,7 @@ import subprocess import tempfile import re +import logging TEST_EXIT_PASSED = 0 TEST_EXIT_SKIPPED = 77 @@ -160,6 +161,7 @@ def main(): parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).') parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit') parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.') + parser.add_argument('--quiet', '-q', action='store_true', help='only print results summary and failure logs') parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.') args, unknown_args = parser.parse_known_args() @@ -171,6 +173,10 @@ def main(): config = configparser.ConfigParser() config.read_file(open(os.path.dirname(__file__) + "/config.ini")) + # Set up logging + logging_level = logging.INFO if args.quiet else logging.DEBUG + logging.basicConfig(format='%(message)s', level=logging_level) + enable_wallet = config["components"].getboolean("ENABLE_WALLET") enable_utils = config["components"].getboolean("ENABLE_UTILS") enable_bitcoind = config["components"].getboolean("ENABLE_BITCOIND") @@ -257,7 +263,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal if enable_coverage: coverage = RPCCoverage() flags.append(coverage.flag) - print("Initializing coverage directory at %s\n" % coverage.dir) + logging.debug("Initializing coverage directory at %s" % coverage.dir) else: coverage = None @@ -273,16 +279,20 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal job_queue = TestHandler(jobs, tests_dir, test_list, flags) max_len_name = len(max(test_list, key=len)) - results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] + results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] for _ in range(len(test_list)): (name, stdout, stderr, status, duration) = job_queue.get_next() all_passed = all_passed and status != "Failed" time_sum += duration - print('\n' + BOLD[1] + name + BOLD[0] + ":") - print('' if status == "Passed" else stdout + '\n', end='') - print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='') - print("Status: %s%s%s, Duration: %s s\n" % (BOLD[1], status, BOLD[0], duration)) + if status == "Passed": + logging.debug("\n%s%s%s passed, Duration: %s s" % (BOLD[1], name, BOLD[0], duration)) + elif status == "Skipped": + logging.debug("\n%s%s%s skipped" % (BOLD[1], name, BOLD[0])) + else: + print("\n%s%s%s failed, Duration: %s s\n" % (BOLD[1], name, BOLD[0], duration)) + print(BOLD[1] + 'stdout:\n' + BOLD[0] + stdout + '\n') + print(BOLD[1] + 'stderr:\n' + BOLD[0] + stderr + '\n') results += "%s | %s | %s s\n" % (name.ljust(max_len_name), status.ljust(7), duration) @@ -293,7 +303,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal if coverage: coverage.report_rpc_coverage() - print("Cleaning up coverage data") + logging.debug("Cleaning up coverage data") coverage.cleanup() sys.exit(not all_passed) From 22c4cd7b0912b3eef1d29d024ab67124ad79004f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 7 Apr 2017 16:20:39 +0200 Subject: [PATCH 192/987] Merge #10159: [tests] color test results and sort alphabetically d80baaa fixup - align summary row correctly and make colors/glyphs globals (John Newbery) bb92d83 [tests] Add unicode symbols for tests passing/failing/skipping (John Newbery) 63062bd [tests] color test results and sort alphabetically (John Newbery) Tree-SHA512: a5b85c05480722abd6e483d1817b7527ca487b8bb8292bc81efba158df5a619b8103ed43b790396071ab0710f39457895a79460480044324798c81331bbade5a --- test/functional/test_runner.py | 93 +++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 28b69b951946..e9f6c0cb1c5f 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -25,6 +25,19 @@ import re import logging +# Formatting. Default colors to empty strings. +BOLD, BLUE, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "") +TICK = "✓ " +CROSS = "✖ " +CIRCLE = "○ " +if os.name == 'posix': + # primitive formatting on supported + # terminal via ANSI escape sequences: + BOLD = ('\033[0m', '\033[1m') + BLUE = ('\033[0m', '\033[0;34m') + RED = ('\033[0m', '\033[0;31m') + GREY = ('\033[0m', '\033[1;30m') + TEST_EXIT_PASSED = 0 TEST_EXIT_SKIPPED = 77 @@ -245,11 +258,6 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal if os.path.isdir(cache_dir): print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir)) - BOLD = ("","") - if os.name == 'posix': - # primitive formatting on supported - # terminal via ANSI escape sequences: - BOLD = ('\033[0m', '\033[1m') #Set env vars if "BITCOIND" not in os.environ: @@ -272,33 +280,26 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal subprocess.check_output([tests_dir + 'create_cache.py'] + flags) #Run Tests - all_passed = True - time_sum = 0 - time0 = time.time() - job_queue = TestHandler(jobs, tests_dir, test_list, flags) + time0 = time.time() + test_results = [] max_len_name = len(max(test_list, key=len)) - results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] + for _ in range(len(test_list)): - (name, stdout, stderr, status, duration) = job_queue.get_next() - all_passed = all_passed and status != "Failed" - time_sum += duration - - if status == "Passed": - logging.debug("\n%s%s%s passed, Duration: %s s" % (BOLD[1], name, BOLD[0], duration)) - elif status == "Skipped": - logging.debug("\n%s%s%s skipped" % (BOLD[1], name, BOLD[0])) + test_result, stdout, stderr = job_queue.get_next() + test_results.append(test_result) + + if test_result.status == "Passed": + logging.debug("\n%s%s%s passed, Duration: %s s" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) + elif test_result.status == "Skipped": + logging.debug("\n%s%s%s skipped" % (BOLD[1], test_result.name, BOLD[0])) else: - print("\n%s%s%s failed, Duration: %s s\n" % (BOLD[1], name, BOLD[0], duration)) + print("\n%s%s%s failed, Duration: %s s\n" % (BOLD[1], test_result.name, BOLD[0], test_result.time)) print(BOLD[1] + 'stdout:\n' + BOLD[0] + stdout + '\n') print(BOLD[1] + 'stderr:\n' + BOLD[0] + stderr + '\n') - results += "%s | %s | %s s\n" % (name.ljust(max_len_name), status.ljust(7), duration) - - results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(7), time_sum) + BOLD[0] - print(results) - print("\nRuntime: %s s" % (int(time.time() - time0))) + print_results(test_results, max_len_name, (int(time.time() - time0))) if coverage: coverage.report_rpc_coverage() @@ -306,8 +307,28 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal logging.debug("Cleaning up coverage data") coverage.cleanup() + all_passed = all(map(lambda test_result: test_result.status == "Passed", test_results)) + sys.exit(not all_passed) +def print_results(test_results, max_len_name, runtime): + results = "\n" + BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] + + test_results.sort(key=lambda result: result.name.lower()) + all_passed = True + time_sum = 0 + + for test_result in test_results: + all_passed = all_passed and test_result.status != "Failed" + time_sum += test_result.time + test_result.padding = max_len_name + results += str(test_result) + + status = TICK + "Passed" if all_passed else CROSS + "Failed" + results += BOLD[1] + "\n%s | %s | %s s (accumulated) \n" % ("ALL".ljust(max_len_name), status.ljust(9), time_sum) + BOLD[0] + results += "Runtime: %s s\n" % (runtime) + print(results) + class TestHandler: """ Trigger the testscrips passed in via the list. @@ -362,9 +383,31 @@ def get_next(self): status = "Failed" self.num_running -= 1 self.jobs.remove(j) - return name, stdout, stderr, status, int(time.time() - time0) + + return TestResult(name, status, int(time.time() - time0)), stdout, stderr print('.', end='', flush=True) +class TestResult(): + def __init__(self, name, status, time): + self.name = name + self.status = status + self.time = time + self.padding = 0 + + def __repr__(self): + if self.status == "Passed": + color = BLUE + glyph = TICK + elif self.status == "Failed": + color = RED + glyph = CROSS + elif self.status == "Skipped": + color = GREY + glyph = CIRCLE + + return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(7), self.time) + color[0] + + def check_script_list(src_dir): """Check scripts directory. From 73a5d9bfdd8ec948a624e2713ad547e1b0f4c58f Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 18 Jun 2019 01:24:59 -0500 Subject: [PATCH 193/987] add `--quiet` to `test_runner.py`, replicates bitcoin#10105 Signed-off-by: Pasta --- ci/test_integrationtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/test_integrationtests.sh b/ci/test_integrationtests.sh index 1210291c8e2d..456a6d2aa114 100755 --- a/ci/test_integrationtests.sh +++ b/ci/test_integrationtests.sh @@ -17,4 +17,4 @@ export LD_LIBRARY_PATH=$BUILD_DIR/depends/$HOST/lib cd build-ci/dashcore-$BUILD_TARGET -./test/functional/test_runner.py --coverage $PASS_ARGS +./test/functional/test_runner.py --coverage --quiet $PASS_ARGS From 2756cb7954ccca546dd9bda158b907b09de41a79 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Tue, 18 Jun 2019 06:32:12 -0500 Subject: [PATCH 194/987] remove spork 12 (#2754) Signed-off-by: Pasta --- src/rpc/misc.cpp | 1 - src/spork.cpp | 36 ----------------------------------- src/spork.h | 8 -------- src/validation.cpp | 47 ---------------------------------------------- src/validation.h | 6 ------ 5 files changed, 98 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 159273cbe1c7..807a6c86a28b 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -302,7 +302,6 @@ UniValue spork(const JSONRPCRequest& request) //broadcast new spork if(sporkManager.UpdateSpork(nSporkID, nValue, *g_connman)){ - sporkManager.ExecuteSpork(nSporkID, nValue); return "success"; } else { throw std::runtime_error( diff --git a/src/spork.cpp b/src/spork.cpp index 76f3df049697..a414160b2a44 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -22,7 +22,6 @@ std::vector sporkDefs = { MAKE_SPORK_DEF(SPORK_5_INSTANTSEND_MAX_VALUE, 1000), // 1000 Dash MAKE_SPORK_DEF(SPORK_6_NEW_SIGS, 4070908800ULL), // OFF MAKE_SPORK_DEF(SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL), // OFF - MAKE_SPORK_DEF(SPORK_12_RECONSIDER_BLOCKS, 0), // 0 BLOCKS MAKE_SPORK_DEF(SPORK_15_DETERMINISTIC_MNS_ENABLED, 4070908800ULL), // OFF MAKE_SPORK_DEF(SPORK_16_INSTANTSEND_AUTOLOCKS, 4070908800ULL), // OFF MAKE_SPORK_DEF(SPORK_17_QUORUM_DKG_ENABLED, 4070908800ULL), // OFF @@ -184,12 +183,6 @@ void CSporkManager::ProcessSpork(CNode* pfrom, const std::string& strCommand, CD } spork.Relay(connman); - //does a task if needed - int64_t nActiveValue = 0; - if (SporkValueIsActive(spork.nSporkID, nActiveValue)) { - ExecuteSpork(spork.nSporkID, nActiveValue); - } - } else if (strCommand == NetMsgType::GETSPORKS) { LOCK(cs); // make sure to not lock this together with cs_main for (const auto& pair : mapSporksActive) { @@ -201,35 +194,6 @@ void CSporkManager::ProcessSpork(CNode* pfrom, const std::string& strCommand, CD } -void CSporkManager::ExecuteSpork(SporkId nSporkID, int nValue) -{ - //correct fork via spork technology - if(nSporkID == SPORK_12_RECONSIDER_BLOCKS && nValue > 0) { - // allow to reprocess 24h of blocks max, which should be enough to resolve any issues - int64_t nMaxBlocks = 576; - // this potentially can be a heavy operation, so only allow this to be executed once per 10 minutes - int64_t nTimeout = 10 * 60; - - static int64_t nTimeExecuted = 0; // i.e. it was never executed before - - if(GetTime() - nTimeExecuted < nTimeout) { - LogPrint(BCLog::SPORK, "CSporkManager::ExecuteSpork -- ERROR: Trying to reconsider blocks, too soon - %d/%d\n", GetTime() - nTimeExecuted, nTimeout); - return; - } - - if(nValue > nMaxBlocks) { - LogPrintf("CSporkManager::ExecuteSpork -- ERROR: Trying to reconsider too many blocks %d/%d\n", nValue, nMaxBlocks); - return; - } - - - LogPrintf("CSporkManager::ExecuteSpork -- Reconsider Last %d Blocks\n", nValue); - - ReprocessBlocks(nValue); - nTimeExecuted = GetTime(); - } -} - bool CSporkManager::UpdateSpork(SporkId nSporkID, int64_t nValue, CConnman& connman) { CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetAdjustedTime()); diff --git a/src/spork.h b/src/spork.h index 1ba09bea839c..1c4efb350688 100644 --- a/src/spork.h +++ b/src/spork.h @@ -26,7 +26,6 @@ enum SporkId : int32_t { SPORK_5_INSTANTSEND_MAX_VALUE = 10004, SPORK_6_NEW_SIGS = 10005, SPORK_9_SUPERBLOCKS_ENABLED = 10008, - SPORK_12_RECONSIDER_BLOCKS = 10011, SPORK_15_DETERMINISTIC_MNS_ENABLED = 10014, SPORK_16_INSTANTSEND_AUTOLOCKS = 10015, SPORK_17_QUORUM_DKG_ENABLED = 10016, @@ -227,13 +226,6 @@ class CSporkManager */ void ProcessSpork(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman); - /** - * ExecuteSpork is used to perform certain actions based on the spork value. - * - * Currently only used with Spork 12. - */ - void ExecuteSpork(SporkId nSporkID, int nValue); - /** * UpdateSpork is used by the spork RPC command to set a new spork value, sign * and broadcast the spork message. diff --git a/src/validation.cpp b/src/validation.cpp index 5a7d8de1dc43..7338234bbbeb 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -105,7 +105,6 @@ CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; CBlockPolicyEstimator feeEstimator; CTxMemPool mempool(&feeEstimator); -std::map mapRejectedBlocks GUARDED_BY(cs_main); static void CheckBlockIndex(const Consensus::Params& consensusParams); @@ -2197,7 +2196,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd // The node which relayed this should switch to correct chain. // TODO: relay instantsend data/proof. LOCK(cs_main); - mapRejectedBlocks.insert(std::make_pair(block.GetHash(), GetTime())); return state.DoS(10, error("ConnectBlock(DASH): transaction %s conflicts with transaction lock %s", tx->GetHash().ToString(), hashLocked.ToString()), REJECT_INVALID, "conflict-tx-lock"); } @@ -2213,7 +2211,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd // The node which relayed this should switch to correct chain. // TODO: relay instantsend data/proof. LOCK(cs_main); - mapRejectedBlocks.insert(std::make_pair(block.GetHash(), GetTime())); return state.DoS(10, error("ConnectBlock(DASH): transaction %s conflicts with transaction lock %s", tx->GetHash().ToString(), conflictLock->txid.ToString()), REJECT_INVALID, "conflict-tx-lock"); } @@ -2242,7 +2239,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd LogPrint(BCLog::BENCHMARK, " - IsBlockValueValid: %.2fms [%.2fs]\n", 0.001 * (nTime5_3 - nTime5_2), nTimeValueValid * 0.000001); if (!IsBlockPayeeValid(*block.vtx[0], pindex->nHeight, blockReward)) { - mapRejectedBlocks.insert(std::make_pair(block.GetHash(), GetTime())); return state.DoS(0, error("ConnectBlock(DASH): couldn't find masternode or superblock payments"), REJECT_INVALID, "bad-cb-payee"); } @@ -2698,49 +2694,6 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, return true; } -bool DisconnectBlocks(int blocks) -{ - LOCK(cs_main); - - CValidationState state; - const CChainParams& chainparams = Params(); - - LogPrintf("DisconnectBlocks -- Got command to replay %d blocks\n", blocks); - for(int i = 0; i < blocks; i++) { - if(!DisconnectTip(state, chainparams) || !state.IsValid()) { - return false; - } - } - - return true; -} - -void ReprocessBlocks(int nBlocks) -{ - LOCK(cs_main); - - std::map::iterator it = mapRejectedBlocks.begin(); - while(it != mapRejectedBlocks.end()){ - //use a window twice as large as is usual for the nBlocks we want to reset - if((*it).second > GetTime() - (nBlocks*60*5)) { - BlockMap::iterator mi = mapBlockIndex.find((*it).first); - if (mi != mapBlockIndex.end() && (*mi).second) { - - CBlockIndex* pindex = (*mi).second; - LogPrintf("ReprocessBlocks -- %s\n", (*it).first.ToString()); - - ResetBlockFailureFlags(pindex); - } - } - ++it; - } - - DisconnectBlocks(nBlocks); - - CValidationState state; - ActivateBestChain(state, Params()); -} - /** * Return the tip of the chain with the most work in it, that isn't * known to be invalid (it's however far from certain to be valid). diff --git a/src/validation.h b/src/validation.h index a87565203050..bd431635be81 100644 --- a/src/validation.h +++ b/src/validation.h @@ -186,8 +186,6 @@ extern int64_t nMaxTipAge; extern bool fLargeWorkForkFound; extern bool fLargeWorkInvalidChainFound; -extern std::map mapRejectedBlocks; - extern std::atomic fDIP0001ActiveAtTip; /** Block hash whose ancestors we will assume to have valid scripts without checking them. */ @@ -455,10 +453,6 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus /** Functions for validating blocks and updating the block tree */ -/** Reprocess a number of blocks to try and get on the correct chain again **/ -bool DisconnectBlocks(int blocks); -void ReprocessBlocks(int nBlocks); - /** Context-independent validity checks */ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true); From f14179ca03d4fedf5798010be3e5d41df63480dc Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Tue, 18 Jun 2019 06:32:43 -0500 Subject: [PATCH 195/987] [Tests] Remove unused variable and inline another variable in evo_deterministicmns_tests.cpp (#2978) * remove unused variable Signed-off-by: Pasta * inline a variable which is used only once Signed-off-by: Pasta --- src/test/evo_deterministicmns_tests.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp index ecf78218dbf1..8b799ffd45c4 100644 --- a/src/test/evo_deterministicmns_tests.cpp +++ b/src/test/evo_deterministicmns_tests.cpp @@ -20,9 +20,6 @@ #include -static const CBitcoinAddress payoutAddress ("yRq1Ky1AfFmf597rnotj7QRxsDUKePVWNF"); -static const std::string payoutKey ("cV3qrPWzDcnhzRMV4MqtTH4LhNPqPo26ZntGvfJhc8nqCi8Ae5xR"); - typedef std::map> SimpleUTXOMap; static SimpleUTXOMap BuildSimpleUtxoMap(const std::vector& txs) @@ -218,6 +215,7 @@ BOOST_FIXTURE_TEST_CASE(dip3_activation, TestChainDIP3BeforeActivationSetup) auto utxos = BuildSimpleUtxoMap(coinbaseTxns); CKey ownerKey; CBLSSecretKey operatorKey; + CBitcoinAddress payoutAddress("yRq1Ky1AfFmf597rnotj7QRxsDUKePVWNF"); auto tx = CreateProRegTx(utxos, 1, GetScriptForDestination(payoutAddress.Get()), coinbaseKey, ownerKey, operatorKey); std::vector txns = {tx}; From 7334aa553caf56a1cb754cfd08ea6078a953bda5 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Tue, 18 Jun 2019 06:33:05 -0500 Subject: [PATCH 196/987] adjust privatesend formatting and follow some best practices (#2979) * adjust privatesend files formatting and follow some best practices * code review Signed-off-by: Pasta * use auto for iterators Signed-off-by: Pasta * review pt2 Signed-off-by: Pasta --- src/privatesend/privatesend-client.cpp | 56 +++++++++++++------------- src/privatesend/privatesend-server.cpp | 39 ++++++++++-------- src/privatesend/privatesend-util.cpp | 4 +- src/privatesend/privatesend.cpp | 23 +++++------ src/privatesend/privatesend.h | 14 +++---- 5 files changed, 71 insertions(+), 65 deletions(-) diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index 0c18806d6cee..c17bcee69d2e 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -99,7 +99,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& int64_t nLastDsq = mmetaman.GetMetaInfo(dmn->proTxHash)->GetLastDsq(); int nThreshold = nLastDsq + mnList.GetValidMNsCount() / 5; LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- nLastDsq: %d threshold: %d nDsqCount: %d\n", nLastDsq, nThreshold, mmetaman.GetDsqCount()); - //don't allow a few nodes to dominate the queuing process + // don't allow a few nodes to dominate the queuing process if (nLastDsq != 0 && nThreshold > mmetaman.GetDsqCount()) { LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- Masternode %s is sending too many dsq messages\n", dmn->proTxHash.ToString()); return; @@ -118,10 +118,9 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& dsq.Relay(connman); } - } else if ( - strCommand == NetMsgType::DSSTATUSUPDATE || - strCommand == NetMsgType::DSFINALTX || - strCommand == NetMsgType::DSCOMPLETE) { + } else if (strCommand == NetMsgType::DSSTATUSUPDATE || + strCommand == NetMsgType::DSFINALTX || + strCommand == NetMsgType::DSCOMPLETE) { LOCK(cs_deqsessions); for (auto& session : deqSessions) { session.ProcessMessage(pfrom, strCommand, vRecv, connman); @@ -201,7 +200,7 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& LogPrint(BCLog::PRIVATESEND, "DSFINALTX -- txNew %s", txNew.ToString()); - //check to see if input is spent already? (and probably not confirmed) + // check to see if input is spent already? (and probably not confirmed) SignFinalTransaction(txNew, pfrom, connman); } else if (strCommand == NetMsgType::DSCOMPLETE) { @@ -294,8 +293,9 @@ std::string CPrivateSendClientSession::GetStatus(bool fWaitForBlock) nStatusMessageProgress += 10; std::string strSuffix = ""; - if (fWaitForBlock || !masternodeSync.IsBlockchainSynced()) + if (fWaitForBlock || !masternodeSync.IsBlockchainSynced()) { return strAutoDenomResult; + } switch (nState) { case POOL_STATE_IDLE: @@ -432,8 +432,7 @@ bool CPrivateSendClientSession::CheckTimeout() int nTimeout = (nState == POOL_STATE_SIGNING) ? PRIVATESEND_SIGNING_TIMEOUT : PRIVATESEND_QUEUE_TIMEOUT; bool fTimeout = GetTime() - nTimeLastSuccessfulStep >= nTimeout + nLagTime; - if (nState == POOL_STATE_IDLE || !fTimeout) - return false; + if (nState == POOL_STATE_IDLE || !fTimeout) return false; LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CheckTimeout -- %s timed out (%ds) -- resetting\n", (nState == POOL_STATE_SIGNING) ? "Signing" : "Session", nTimeout); @@ -481,11 +480,13 @@ bool CPrivateSendClientSession::SendDenominate(const std::vectorHasCollateralInputs()) + if (!pwalletMain->HasCollateralInputs()) { return !pwalletMain->HasCollateralInputs(false) && MakeCollateralAmounts(connman); + } if (nSessionID) { strAutoDenomResult = _("Mixing in progress..."); @@ -962,14 +963,14 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool bool fUseQueue = GetRandInt(100) > 33; // don't use the queues all of the time for mixing unless we are a liquidity provider - if ((privateSendClient.nLiquidityProvider || fUseQueue) && JoinExistingQueue(nBalanceNeedsAnonymized, connman)) + if ((privateSendClient.nLiquidityProvider || fUseQueue) && JoinExistingQueue(nBalanceNeedsAnonymized, connman)) { return true; + } // do not initiate queue if we are a liquidity provider to avoid useless inter-mixing if (privateSendClient.nLiquidityProvider) return false; - if (StartNewQueue(nBalanceNeedsAnonymized, connman)) - return true; + if (StartNewQueue(nBalanceNeedsAnonymized, connman)) return true; strAutoDenomResult = _("No compatible Masternode found."); return false; @@ -1013,8 +1014,7 @@ bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool deqSessions.emplace_back(); } for (auto& session : deqSessions) { - if (!CheckAutomaticBackup()) - return false; + if (!CheckAutomaticBackup()) return false; if (WaitForAnotherBlock()) { LogPrintf("CPrivateSendClientManager::DoAutomaticDenominating -- Last successful PrivateSend action was too recent\n"); @@ -1456,8 +1456,9 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta LOCK2(cs_main, pwalletMain->cs_wallet); // denominated input is always a single one, so we can check its amount directly and return early - if (!fTryDenominated && tallyItem.vecOutPoints.size() == 1 && CPrivateSend::IsDenominatedAmount(tallyItem.nAmount)) + if (!fTryDenominated && tallyItem.vecOutPoints.size() == 1 && CPrivateSend::IsDenominatedAmount(tallyItem.nAmount)) { return false; + } CWalletTx wtx; CAmount nFeeRet = 0; @@ -1483,8 +1484,9 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta coinControl.fAllowWatchOnly = false; // send change to the same address so that we were able create more denoms out of it later coinControl.destChange = tallyItem.txdest; - for (const auto& outpoint : tallyItem.vecOutPoints) + for (const auto& outpoint : tallyItem.vecOutPoints) { coinControl.Select(outpoint); + } bool fSuccess = pwalletMain->CreateTransaction(vecSend, wtx, reservekeyChange, nFeeRet, nChangePosRet, strFail, &coinControl, true, ONLY_NONDENOMINATED); @@ -1643,8 +1645,9 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, coinControl.fAllowWatchOnly = false; // send change to the same address so that we were able create more denoms out of it later coinControl.destChange = tallyItem.txdest; - for (const auto& outpoint : tallyItem.vecOutPoints) + for (const auto& outpoint : tallyItem.vecOutPoints) { coinControl.Select(outpoint); + } CWalletTx wtx; CAmount nFeeRet = 0; @@ -1705,8 +1708,7 @@ void CPrivateSendClientManager::DoMaintenance(CConnman& connman) if (fLiteMode) return; // disable all Dash specific functionality if (fMasternodeMode) return; // no client-side mixing on masternodes - if (!masternodeSync.IsBlockchainSynced() || ShutdownRequested()) - return; + if (!masternodeSync.IsBlockchainSynced() || ShutdownRequested()) return; static unsigned int nTick = 0; static unsigned int nDoAutoNextRun = nTick + PRIVATESEND_AUTO_TIMEOUT_MIN; diff --git a/src/privatesend/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp index 12d8c3e41986..bfe1ce4b510d 100644 --- a/src/privatesend/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -55,7 +55,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm return; } - if (vecSessionCollaterals.size() == 0) { + if (vecSessionCollaterals.empty()) { { TRY_LOCK(cs_vecqueue, lockRecv); if (!lockRecv) return; @@ -185,14 +185,14 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm return; } - //do we have the same denominations as the current session? + // do we have the same denominations as the current session? if (!IsOutputsCompatibleWithSessionDenom(entry.vecTxOut)) { LogPrintf("DSVIN -- not compatible with existing transactions!\n"); PushStatus(pfrom, STATUS_REJECTED, ERR_EXISTING_TX, connman); return; } - //check it like a transaction + // check it like a transaction { CAmount nValueIn = 0; CAmount nValueOut = 0; @@ -343,11 +343,12 @@ void CPrivateSendServer::CreateFinalTransaction(CConnman& connman) // make our new transaction for (int i = 0; i < GetEntriesCount(); i++) { - for (const auto& txout : vecEntries[i].vecTxOut) + for (const auto& txout : vecEntries[i].vecTxOut) { txNew.vout.push_back(txout); - - for (const auto& txdsin : vecEntries[i].vecTxDSIn) + } + for (const auto& txdsin : vecEntries[i].vecTxDSIn) { txNew.vin.push_back(txdsin); + } } sort(txNew.vin.begin(), txNew.vin.end(), CompareInputBIP69()); @@ -375,7 +376,7 @@ void CPrivateSendServer::CommitFinalTransaction(CConnman& connman) TRY_LOCK(cs_main, lockMain); CValidationState validationState; mempool.PrioritiseTransaction(hashTx, 0.1 * COIN); - if (!lockMain || !AcceptToMemoryPool(mempool, validationState, finalTransaction, false, NULL, false, maxTxFee, true)) { + if (!lockMain || !AcceptToMemoryPool(mempool, validationState, finalTransaction, false, nullptr, false, maxTxFee, true)) { LogPrintf("CPrivateSendServer::CommitFinalTransaction -- AcceptToMemoryPool() error: Transaction not valid\n"); SetNull(); // not much we can do in this case, just notify clients @@ -433,9 +434,12 @@ void CPrivateSendServer::ChargeFees(CConnman& connman) if (nState == POOL_STATE_ACCEPTING_ENTRIES) { for (const auto& txCollateral : vecSessionCollaterals) { bool fFound = false; - for (const auto& entry : vecEntries) - if (*entry.txCollateral == *txCollateral) + for (const auto& entry : vecEntries) { + if (*entry.txCollateral == *txCollateral) { fFound = true; + break; + } + } // This queue entry didn't send us the promised transaction if (!fFound) { @@ -584,9 +588,9 @@ bool CPrivateSendServer::IsInputScriptSigValid(const CTxIn& txin) CScript sigPubKey = CScript(); for (const auto& entry : vecEntries) { - for (const auto& txout : entry.vecTxOut) + for (const auto& txout : entry.vecTxOut) { txNew.vout.push_back(txout); - + } for (const auto& txdsin : entry.vecTxDSIn) { txNew.vin.push_back(txdsin); @@ -702,9 +706,11 @@ bool CPrivateSendServer::AddScriptSig(const CTxIn& txinNew) // Check to make sure everything is signed bool CPrivateSendServer::IsSignaturesComplete() { - for (const auto& entry : vecEntries) - for (const auto& txdsin : entry.vecTxDSIn) + for (const auto& entry : vecEntries) { + for (const auto& txdsin : entry.vecTxDSIn) { if (!txdsin.fHasSig) return false; + } + } return true; } @@ -827,7 +833,7 @@ void CPrivateSendServer::RelayFinalTransaction(const CTransaction& txFinal, CCon __func__, nSessionID, nSessionDenom, CPrivateSend::GetDenominationsToString(nSessionDenom)); // final mixing tx with empty signatures should be relayed to mixing participants only - for (const auto entry : vecEntries) { + for (const auto& entry : vecEntries) { bool fOk = connman.ForNode(entry.addr, [&txFinal, &connman, this](CNode* pnode) { CNetMsgMaker msgMaker(pnode->GetSendVersion()); connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSFINALTX, nSessionID, txFinal)); @@ -852,7 +858,7 @@ void CPrivateSendServer::RelayStatus(PoolStatusUpdate nStatusUpdate, CConnman& c { unsigned int nDisconnected{}; // status updates should be relayed to mixing participants only - for (const auto entry : vecEntries) { + for (const auto& entry : vecEntries) { // make sure everyone is still connected bool fOk = connman.ForNode(entry.addr, [&nStatusUpdate, &nMessageID, &connman, this](CNode* pnode) { PushStatus(pnode, nStatusUpdate, nMessageID, connman); @@ -923,8 +929,7 @@ void CPrivateSendServer::DoMaintenance(CConnman& connman) if (fLiteMode) return; // disable all Dash specific functionality if (!fMasternodeMode) return; // only run on masternodes - if (!masternodeSync.IsBlockchainSynced() || ShutdownRequested()) - return; + if (!masternodeSync.IsBlockchainSynced() || ShutdownRequested()) return; privateSendServer.CheckTimeout(connman); privateSendServer.CheckForCompleteQueue(connman); diff --git a/src/privatesend/privatesend-util.cpp b/src/privatesend/privatesend-util.cpp index 9ac8c12d080a..2166e438b5c6 100644 --- a/src/privatesend/privatesend-util.cpp +++ b/src/privatesend/privatesend-util.cpp @@ -46,7 +46,7 @@ void CKeyHolderStorage::KeepAll() std::swap(storage, tmp); } - if (tmp.size() > 0) { + if (!tmp.empty()) { for (auto& key : tmp) { key->KeepKey(); } @@ -63,7 +63,7 @@ void CKeyHolderStorage::ReturnAll() std::swap(storage, tmp); } - if (tmp.size() > 0) { + if (!tmp.empty()) { for (auto& key : tmp) { key->ReturnKey(); } diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 1dd015f857f9..5792bcee1f96 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -74,8 +74,9 @@ bool CPrivateSendQueue::Relay(CConnman& connman) { connman.ForEachNode([&connman, this](CNode* pnode) { CNetMsgMaker msgMaker(pnode->GetSendVersion()); - if (pnode->nVersion >= MIN_PRIVATESEND_PEER_PROTO_VERSION && pnode->fSendDSQueue) + if (pnode->nVersion >= MIN_PRIVATESEND_PEER_PROTO_VERSION && pnode->fSendDSQueue) { connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSQUEUE, (*this))); + } }); return true; } @@ -89,7 +90,6 @@ bool CPrivateSendBroadcastTx::Sign() { if (!fMasternodeMode) return false; - uint256 hash = GetSignatureHash(); CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); @@ -103,7 +103,6 @@ bool CPrivateSendBroadcastTx::Sign() bool CPrivateSendBroadcastTx::CheckSignature(const CBLSPublicKey& blsPubKey) const { - uint256 hash = GetSignatureHash(); CBLSSignature sig; @@ -170,13 +169,14 @@ void CPrivateSendBaseManager::CheckQueue() if (!lockDS) return; // it's ok to fail here, we run this quite frequently // check mixing queue objects for timeouts - std::vector::iterator it = vecPrivateSendQueue.begin(); + auto it = vecPrivateSendQueue.begin(); while (it != vecPrivateSendQueue.end()) { if ((*it).IsExpired()) { LogPrint(BCLog::PRIVATESEND, "CPrivateSendBaseManager::%s -- Removing expired queue (%s)\n", __func__, (*it).ToString()); it = vecPrivateSendQueue.erase(it); - } else + } else { ++it; + } } } @@ -350,8 +350,9 @@ int CPrivateSend::GetDenominations(const std::vector& vecTxOut, bool fSi std::vector > vecDenomUsed; // make a list of denominations, with zero uses - for (const auto& nDenomValue : vecStandardDenominations) + for (const auto& nDenomValue : vecStandardDenominations) { vecDenomUsed.push_back(std::make_pair(nDenomValue, 0)); + } // look for denominations and update uses to 1 for (const auto& txout : vecTxOut) { @@ -415,9 +416,9 @@ int CPrivateSend::GetDenominationsByAmounts(const std::vector& vecAmoun bool CPrivateSend::IsDenominatedAmount(CAmount nInputAmount) { - for (const auto& nDenomValue : vecStandardDenominations) - if (nInputAmount == nDenomValue) - return true; + for (const auto& nDenomValue : vecStandardDenominations) { + if (nInputAmount == nDenomValue) return true; + } return false; } @@ -450,8 +451,6 @@ std::string CPrivateSend::GetMessageByID(PoolMessage nMessageID) return _("Incompatible mode."); case ERR_NON_STANDARD_PUBKEY: return _("Non-standard public key detected."); - case ERR_NOT_A_MN: - return _("This is not a Masternode."); // not used case ERR_QUEUE_FULL: return _("Masternode queue is full."); case ERR_RECENT: @@ -491,7 +490,7 @@ CPrivateSendBroadcastTx CPrivateSend::GetDSTX(const uint256& hash) void CPrivateSend::CheckDSTXes(int nHeight) { LOCK(cs_mapdstx); - std::map::iterator it = mapDSTX.begin(); + auto it = mapDSTX.begin(); while (it != mapDSTX.end()) { if (it->second.IsExpired(nHeight)) { mapDSTX.erase(it++); diff --git a/src/privatesend/privatesend.h b/src/privatesend/privatesend.h index 0a0534b44947..f5d189f2726e 100644 --- a/src/privatesend/privatesend.h +++ b/src/privatesend/privatesend.h @@ -75,7 +75,7 @@ enum PoolStatusUpdate { STATUS_ACCEPTED }; -/** Holds an mixing input +/** Holds a mixing input */ class CTxDSIn : public CTxIn { @@ -128,7 +128,7 @@ class CPrivateSendAccept } }; -// A clients transaction in the mixing pool +// A client's transaction in the mixing pool class CPrivateSendEntry { public: @@ -147,10 +147,10 @@ class CPrivateSendEntry } CPrivateSendEntry(const std::vector& vecTxDSIn, const std::vector& vecTxOut, const CTransaction& txCollateral) : - vecTxDSIn(vecTxDSIn), - vecTxOut(vecTxOut), - txCollateral(MakeTransactionRef(txCollateral)), - addr(CService()) + vecTxDSIn(vecTxDSIn), + vecTxOut(vecTxOut), + txCollateral(MakeTransactionRef(txCollateral)), + addr(CService()) { } @@ -332,7 +332,7 @@ class CPrivateSendBaseSession void SetNull(); public: - int nSessionDenom; //Users must submit a denom matching this + int nSessionDenom; // Users must submit a denom matching this CPrivateSendBaseSession() : vecEntries(), From 8d5781f408adcfc1095d461579835928c8e34405 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 18 Jun 2019 14:33:30 +0300 Subject: [PATCH 197/987] Stop reporting/processing the number of mixing participants in DSSTATUSUPDATE (#2980) * Stop reporting/processing the number of mixing participants * Introduce CPrivateSendStatusUpdate class to encapsulate serialization of DSSTATUSUPDATE msg And make corresponding enums serializable too. * Revert range checks removal --- src/privatesend/privatesend-client.cpp | 77 ++++++++------------------ src/privatesend/privatesend-client.h | 7 +-- src/privatesend/privatesend-server.cpp | 6 +- src/privatesend/privatesend.h | 47 +++++++++++++++- 4 files changed, 71 insertions(+), 66 deletions(-) diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index c17bcee69d2e..3ba39ffd479d 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -147,32 +147,28 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& return; } - int nMsgSessionID; - int nMsgState; - int nMsgEntriesCount; - int nMsgStatusUpdate; - int nMsgMessageID; - vRecv >> nMsgSessionID >> nMsgState >> nMsgEntriesCount >> nMsgStatusUpdate >> nMsgMessageID; - - if (nMsgState < POOL_STATE_MIN || nMsgState > POOL_STATE_MAX) { - LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- nMsgState is out of bounds: %d\n", nMsgState); + CPrivateSendStatusUpdate psssup; + vRecv >> psssup; + + if (psssup.nState < POOL_STATE_MIN || psssup.nState > POOL_STATE_MAX) { + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- psssup.nState is out of bounds: %d\n", psssup.nState); return; } - if (nMsgStatusUpdate < STATUS_REJECTED || nMsgStatusUpdate > STATUS_ACCEPTED) { - LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- nMsgStatusUpdate is out of bounds: %d\n", nMsgStatusUpdate); + if (psssup.nStatusUpdate < STATUS_REJECTED || psssup.nStatusUpdate > STATUS_ACCEPTED) { + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- psssup.nStatusUpdate is out of bounds: %d\n", psssup.nStatusUpdate); return; } - if (nMsgMessageID < MSG_POOL_MIN || nMsgMessageID > MSG_POOL_MAX) { - LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- nMsgMessageID is out of bounds: %d\n", nMsgMessageID); + if (psssup.nMessageID < MSG_POOL_MIN || psssup.nMessageID > MSG_POOL_MAX) { + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- psssup.nMessageID is out of bounds: %d\n", psssup.nMessageID); return; } - LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- nMsgSessionID %d nMsgState: %d nEntriesCount: %d nMsgStatusUpdate: %d nMsgMessageID %d (%s)\n", - nMsgSessionID, nMsgState, nEntriesCount, nMsgStatusUpdate, nMsgMessageID, CPrivateSend::GetMessageByID(PoolMessage(nMsgMessageID))); + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- psssup.nSessionID %d psssup.nState: %d psssup.nStatusUpdate: %d psssup.nMessageID %d (%s)\n", + psssup.nSessionID, psssup.nState, psssup.nStatusUpdate, psssup.nMessageID, CPrivateSend::GetMessageByID(psssup.nMessageID)); - if (!CheckPoolStateUpdate(PoolState(nMsgState), nMsgEntriesCount, PoolStatusUpdate(nMsgStatusUpdate), PoolMessage(nMsgMessageID), nMsgSessionID)) { + if (!CheckPoolStateUpdate(psssup)) { LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- CheckPoolStateUpdate failed\n"); } @@ -217,7 +213,7 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& } int nMsgSessionID; - int nMsgMessageID; + PoolMessage nMsgMessageID; vRecv >> nMsgSessionID >> nMsgMessageID; if (nMsgMessageID < MSG_POOL_MIN || nMsgMessageID > MSG_POOL_MAX) { @@ -230,9 +226,9 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& return; } - LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- nMsgSessionID %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgMessageID, CPrivateSend::GetMessageByID(PoolMessage(nMsgMessageID))); + LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- nMsgSessionID %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgMessageID, CPrivateSend::GetMessageByID(nMsgMessageID)); - CompletedTransaction(PoolMessage(nMsgMessageID)); + CompletedTransaction(nMsgMessageID); } } @@ -258,8 +254,6 @@ void CPrivateSendClientManager::ResetPool() void CPrivateSendClientSession::SetNull() { // Client side - nEntriesCount = 0; - fLastEntryAccepted = false; mixingMasternode = nullptr; pendingDsaRequest = CPendingDsaRequest(); @@ -309,26 +303,7 @@ std::string CPrivateSendClientSession::GetStatus(bool fWaitForBlock) strSuffix = "..."; return strprintf(_("Submitted to masternode, waiting in queue %s"), strSuffix); case POOL_STATE_ACCEPTING_ENTRIES: - if (nEntriesCount == 0) { - nStatusMessageProgress = 0; - return strAutoDenomResult; - } else if (fLastEntryAccepted) { - if (nStatusMessageProgress % 10 > 8) { - fLastEntryAccepted = false; - nStatusMessageProgress = 0; - } - return _("PrivateSend request complete:") + " " + _("Your transaction was accepted into the pool!"); - } else { - if (nStatusMessageProgress % 70 <= 40) - return strprintf(_("Submitted following entries to masternode: %u"), nEntriesCount); - else if (nStatusMessageProgress % 70 <= 50) - strSuffix = "."; - else if (nStatusMessageProgress % 70 <= 60) - strSuffix = ".."; - else if (nStatusMessageProgress % 70 <= 70) - strSuffix = "..."; - return strprintf(_("Submitted to masternode, waiting for more entries ( %u ) %s"), nEntriesCount, strSuffix); - } + return strAutoDenomResult; case POOL_STATE_SIGNING: if (nStatusMessageProgress % 70 <= 40) return _("Found enough users, signing ..."); @@ -532,39 +507,33 @@ bool CPrivateSendClientSession::SendDenominate(const std::vector vecOutPointLocked; - int nEntriesCount; - bool fLastEntryAccepted; - std::string strLastMessage; std::string strAutoDenomResult; @@ -121,7 +118,7 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession bool SendDenominate(const std::vector >& vecPSInOutPairsIn, CConnman& connman); /// Get Masternode updates about the progress of mixing - bool CheckPoolStateUpdate(PoolState nStateNew, int nEntriesCountNew, PoolStatusUpdate nStatusUpdate, PoolMessage nMessageID, int nSessionIDNew = 0); + bool CheckPoolStateUpdate(CPrivateSendStatusUpdate psssup); // Set the 'state' value, with some logging and capturing when the state changed void SetState(PoolState nStateNew); @@ -139,8 +136,6 @@ class CPrivateSendClientSession : public CPrivateSendBaseSession public: CPrivateSendClientSession() : vecOutPointLocked(), - nEntriesCount(0), - fLastEntryAccepted(false), strLastMessage(), strAutoDenomResult(), mixingMasternode(), diff --git a/src/privatesend/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp index bfe1ce4b510d..607f864b3fbf 100644 --- a/src/privatesend/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -850,8 +850,8 @@ void CPrivateSendServer::RelayFinalTransaction(const CTransaction& txFinal, CCon void CPrivateSendServer::PushStatus(CNode* pnode, PoolStatusUpdate nStatusUpdate, PoolMessage nMessageID, CConnman& connman) { if (!pnode) return; - CNetMsgMaker msgMaker(pnode->GetSendVersion()); - connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSSTATUSUPDATE, nSessionID, (int)nState, (int)vecEntries.size(), (int)nStatusUpdate, (int)nMessageID)); + CPrivateSendStatusUpdate psssup(nSessionID, nState, 0, nStatusUpdate, nMessageID); + connman.PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::DSSTATUSUPDATE, psssup)); } void CPrivateSendServer::RelayStatus(PoolStatusUpdate nStatusUpdate, CConnman& connman, PoolMessage nMessageID) @@ -899,7 +899,7 @@ void CPrivateSendServer::RelayCompletedTransaction(PoolMessage nMessageID, CConn for (const auto& entry : vecEntries) { bool fOk = connman.ForNode(entry.addr, [&nMessageID, &connman, this](CNode* pnode) { CNetMsgMaker msgMaker(pnode->GetSendVersion()); - connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSCOMPLETE, nSessionID, (int)nMessageID)); + connman.PushMessage(pnode, msgMaker.Make(NetMsgType::DSCOMPLETE, nSessionID, nMessageID)); return true; }); if (!fOk) { diff --git a/src/privatesend/privatesend.h b/src/privatesend/privatesend.h index f5d189f2726e..5a2872bcd0c8 100644 --- a/src/privatesend/privatesend.h +++ b/src/privatesend/privatesend.h @@ -29,7 +29,7 @@ static const int MIN_PRIVATESEND_PEER_PROTO_VERSION = 70213; static const size_t PRIVATESEND_ENTRY_MAX_SIZE = 9; // pool responses -enum PoolMessage { +enum PoolMessage : int32_t { ERR_ALREADY_HAVE, ERR_DENOM, ERR_ENTRIES_FULL, @@ -56,9 +56,10 @@ enum PoolMessage { MSG_POOL_MIN = ERR_ALREADY_HAVE, MSG_POOL_MAX = ERR_SIZE_MISMATCH }; +template<> struct is_serializable_enum : std::true_type {}; // pool states -enum PoolState { +enum PoolState : int32_t { POOL_STATE_IDLE, POOL_STATE_QUEUE, POOL_STATE_ACCEPTING_ENTRIES, @@ -68,12 +69,52 @@ enum PoolState { POOL_STATE_MIN = POOL_STATE_IDLE, POOL_STATE_MAX = POOL_STATE_SUCCESS }; +template<> struct is_serializable_enum : std::true_type {}; // status update message constants -enum PoolStatusUpdate { +enum PoolStatusUpdate : int32_t { STATUS_REJECTED, STATUS_ACCEPTED }; +template<> struct is_serializable_enum : std::true_type {}; + +class CPrivateSendStatusUpdate +{ +public: + int nSessionID; + PoolState nState; + int nEntriesCount; // deprecated, kept for backwards compatibility + PoolStatusUpdate nStatusUpdate; + PoolMessage nMessageID; + + CPrivateSendStatusUpdate() : + nSessionID(0), + nState(POOL_STATE_IDLE), + nEntriesCount(0), + nStatusUpdate(STATUS_ACCEPTED), + nMessageID(MSG_NOERR) {}; + + CPrivateSendStatusUpdate(int nSessionID, PoolState nState, int nEntriesCount, PoolStatusUpdate nStatusUpdate, PoolMessage nMessageID) : + nSessionID(nSessionID), + nState(nState), + nEntriesCount(nEntriesCount), + nStatusUpdate(nStatusUpdate), + nMessageID(nMessageID) {}; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(nSessionID); + READWRITE(nState); + if (s.GetVersion() <= 702015) { + READWRITE(nEntriesCount); + } + READWRITE(nStatusUpdate); + READWRITE(nMessageID); + } +}; /** Holds a mixing input */ From d63202bdced93ed0dfbb0b2b1a497971a0f7b081 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 18 Jun 2019 14:33:44 +0300 Subject: [PATCH 198/987] Should send "reject" when mixing queue is full (#2981) --- src/privatesend/privatesend-server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/privatesend/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp index 607f864b3fbf..4b08c61ae4d7 100644 --- a/src/privatesend/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -39,7 +39,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (IsSessionReady()) { // too many users in this session already, reject new ones LogPrintf("DSACCEPT -- queue is already full!\n"); - PushStatus(pfrom, STATUS_ACCEPTED, ERR_QUEUE_FULL, connman); + PushStatus(pfrom, STATUS_REJECTED, ERR_QUEUE_FULL, connman); return; } From 6677a614a74fd47f250098203e62502a3b8fed5e Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 18 Jun 2019 13:34:00 +0200 Subject: [PATCH 199/987] Run extended tests when Travis is started through cron (#2983) This allows daily testing of extended tests. The --exclude also contains "dbcrash", which we haven't backported yet, but I decided to leave it in when I copied the code from Bitcoin, so that we later don't forget to add it. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 47f090dfc879..6ded5c378585 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,8 @@ runtests: &runtests - $DOCKER_RUN_IN_BUILDER ./ci/build_depends.sh - $DOCKER_RUN_IN_BUILDER ./ci/build_src.sh - $DOCKER_RUN_IN_BUILDER ./ci/test_unittests.sh - - $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh --jobs=3 + - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then extended="--extended --exclude pruning,dbcrash"; fi + - $DOCKER_RUN_IN_BUILDER ./ci/test_integrationtests.sh --jobs=3 ${extended} builddocker: &builddocker stage: build docker From 2e13d1305c0a702349ad9dae92c0eab902070b9c Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 18 Jun 2019 13:34:16 +0200 Subject: [PATCH 200/987] Add some comments to make quorum merkle root calculation more clear+ (#2984) This should avoid future confusion. --- src/evo/cbtx.cpp | 4 ++++ src/llmq/quorums_blockprocessor.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 1778e171cc0c..ed180627a5d1 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -155,6 +155,7 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre static std::map> quorumsCached; static std::map> qcHashesCached; + // The returned quorums are in reversed order, so the most recent one is at index 0 auto quorums = llmq::quorumBlockProcessor->GetMinedAndActiveCommitmentsUntilBlock(pindexPrev); std::map> qcHashes; size_t hashCount = 0; @@ -201,6 +202,9 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre const auto& params = Params().GetConsensus().llmqs.at((Consensus::LLMQType)qc.commitment.llmqType); auto& v = qcHashes[params.type]; if (v.size() == params.signingActiveQuorumCount) { + // we pop the last entry, which is actually the oldest quorum as GetMinedAndActiveCommitmentsUntilBlock + // returned quorums in reversed order. This pop and later push can only work ONCE, but we rely on the + // fact that a block can only contain a single commitment for one LLMQ type v.pop_back(); } v.emplace_back(qcHash); diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index e7ddde295791..d44616cbd8bc 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -405,6 +405,7 @@ bool CQuorumBlockProcessor::GetMinedCommitment(Consensus::LLMQType llmqType, con return true; } +// The returned quorums are in reversed order, so the most recent one is at index 0 std::vector CQuorumBlockProcessor::GetMinedCommitmentsUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t maxCount) { auto dbIt = evoDb.GetCurTransaction().NewIteratorUniquePtr(); @@ -446,6 +447,7 @@ std::vector CQuorumBlockProcessor::GetMinedCommitmentsUntilB return ret; } +// The returned quorums are in reversed order, so the most recent one is at index 0 std::map> CQuorumBlockProcessor::GetMinedAndActiveCommitmentsUntilBlock(const CBlockIndex* pindex) { std::map> ret; From f84d5d46d3ae056f87fa6127e8fa430c9a4612e8 Mon Sep 17 00:00:00 2001 From: Amir Abrams Date: Tue, 18 Jun 2019 06:34:36 -0500 Subject: [PATCH 201/987] QT: Revert "Force TLS1.0+ for SSL connections" (#2985) See: https://github.com/bitcoin/bitcoin/commit/0242b5afa4ebb381d3a59a7246348a50d3a7fdbe This reverts commit 15e26a6, whose purpose was to tweak the Qt configuration to force TLS, i.e., to disable SSLv3, in Qt versions >= 5.5. However, the default behavior of Qt >= 5.4 is to disable SSLv3 anyway [1], so the configuration tweak is redundant. With Qt 5.11.2, the configuration tweak is not only redundant but in fact provokes a deadlock (#14359) due to Qt 5.11.2 being incompatible with OpenSSL 1.1.1 [2]. Since the deadlock occurs at the early startup stage of bitcoin-qt, it renders bitcoin-qt entirely non-functional when compiled against OpenSSL 1.1.1 and Qt 5.11.2 (and possible future combinations of OpenSSL and Qt versions). This commit fixes #14359 by removing the redundant code. [1] https://code.qt.io/cgit/qt/qtbase.git/commit/?id=3fd2d9eff8c1f948306ee5fbfe364ccded1c4b84 [2] https://bugreports.qt.io/browse/QTBUG-70956 --- src/qt/dash.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp index 1f351bc839a2..4cd47236c964 100644 --- a/src/qt/dash.cpp +++ b/src/qt/dash.cpp @@ -54,7 +54,6 @@ #include #include #include -#include #if defined(QT_STATICPLUGIN) #include @@ -601,13 +600,6 @@ int main(int argc, char *argv[]) #ifdef Q_OS_MAC QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); #endif -#if QT_VERSION >= 0x050500 - // Because of the POODLE attack it is recommended to disable SSLv3 (https://disablessl3.com/), - // so set SSL protocols to TLS1.0+. - QSslConfiguration sslconf = QSslConfiguration::defaultConfiguration(); - sslconf.setProtocol(QSsl::TlsV1_0OrLater); - QSslConfiguration::setDefaultConfiguration(sslconf); -#endif // Register meta types used for QMetaObject::invokeMethod qRegisterMetaType< bool* >(); From fc5e461eebe3601b81f788526efbeccf73ad62df Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 17 Apr 2017 21:54:27 +0200 Subject: [PATCH 202/987] Merge #10222: [tests] test_runner - check unicode a97ed80 [tests] test_runner - check unicode (John Newbery) Tree-SHA512: f395297b854a967ad81eed9b822a8f33660fa2ffb9b3bd8fb3b287c32caf5792bd53faad836602f45a5e302800e04d2723d5107531f3643fbf1895e35f98d2ba --- test/functional/test_runner.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index e9f6c0cb1c5f..6bcdd629e191 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -27,9 +27,17 @@ # Formatting. Default colors to empty strings. BOLD, BLUE, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "") -TICK = "✓ " -CROSS = "✖ " -CIRCLE = "○ " +try: + # Make sure python thinks it can write unicode to its stdout + "\u2713".encode("utf_8").decode(sys.stdout.encoding) + TICK = "✓ " + CROSS = "✖ " + CIRCLE = "○ " +except UnicodeDecodeError: + TICK = "P " + CROSS = "x " + CIRCLE = "o " + if os.name == 'posix': # primitive formatting on supported # terminal via ANSI escape sequences: From 310ff00e6516562eea50581c36fdda35184bd690 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 2 May 2017 14:50:25 +0200 Subject: [PATCH 203/987] Merge #10175: Remove excess logic. 9a763d4 Remove excess logic. (practicalswift) Tree-SHA512: cfef280cc9cccf5042c9c49a8cd6fb6700764671cdd0d988149121f56c2d43a9ac38c5fc99c92385a9619d2d846480e02a9d655fa2586b1c284961b4634c229b fix 10175 Signed-off-by: Pasta fix 10175 Signed-off-by: Pasta fix 10175 Signed-off-by: Pasta --- src/miner.cpp | 4 +--- src/qt/bantablemodel.cpp | 4 +--- src/validation.cpp | 5 +---- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index 676ed7c8fd10..b0e2f0da3c60 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -342,9 +342,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already bool BlockAssembler::SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx) { assert (it != mempool.mapTx.end()); - if (mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it)) - return true; - return false; + return mapModifiedTx.count(it) || inBlock.count(it) || failedTx.count(it); } void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, CTxMemPool::txiter entry, std::vector& sortedEntries) diff --git a/src/qt/bantablemodel.cpp b/src/qt/bantablemodel.cpp index ee46feed3179..391d509b263e 100644 --- a/src/qt/bantablemodel.cpp +++ b/src/qt/bantablemodel.cpp @@ -181,7 +181,5 @@ void BanTableModel::sort(int column, Qt::SortOrder order) bool BanTableModel::shouldShow() { - if (priv->size() > 0) - return true; - return false; + return priv->size() > 0; } diff --git a/src/validation.cpp b/src/validation.cpp index 35745693957e..e49206cf3102 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1337,10 +1337,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight) bool CScriptCheck::operator()() { const CScript &scriptSig = ptxTo->vin[nIn].scriptSig; PrecomputedTransactionData txdata(*ptxTo); - if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, txdata, cacheStore), &error)) { - return false; - } - return true; + return VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, txdata, cacheStore), &error); } int GetSpendHeight(const CCoinsViewCache& inputs) From 7c47cae0605fe202f38eb9e766c9ed151739ab4e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 2 May 2017 20:02:55 +0200 Subject: [PATCH 204/987] Merge #10198: [tests] Remove is_network_split from functional test framework c9cc76d [tests] Remove is_network_split from funtional test cases (John Newbery) Tree-SHA512: a43ec63a7dc20cbe9048f8d3af755aef55e9247f605d6481e6d665112882a749af7514f29c83ca9d761421b8e0f7282e5b9f8fc471985d222de826da7cc80ccf Signed-off-by: Pasta --- test/functional/abandonconflict.py | 7 +-- test/functional/bip65-cltv-p2p.py | 7 +-- test/functional/bip65-cltv.py | 7 +-- test/functional/bip68-112-113-p2p.py | 9 +--- test/functional/bip68-sequence.py | 9 +--- test/functional/bip9-softforks.py | 6 +-- test/functional/bipdersig-p2p.py | 6 --- test/functional/bipdersig.py | 7 +-- test/functional/blockchain.py | 5 -- test/functional/decodescript.py | 4 -- test/functional/disablewallet.py | 6 +-- test/functional/disconnect_ban.py | 4 -- test/functional/forknotify.py | 3 -- test/functional/fundrawtransaction.py | 14 ++--- test/functional/getblocktemplate_proposals.py | 4 -- test/functional/getchaintips.py | 2 +- test/functional/httpbasics.py | 2 +- test/functional/importmulti.py | 5 +- test/functional/importprunedfunds.py | 6 --- test/functional/invalidateblock.py | 11 ++-- test/functional/keypool.py | 3 -- test/functional/listsinceblock.py | 4 +- test/functional/listtransactions.py | 5 ++ test/functional/maxuploadtarget.py | 6 +-- test/functional/mempool_limit.py | 19 +++---- test/functional/mempool_packages.py | 9 +--- test/functional/mempool_reorg.py | 10 +--- test/functional/mempool_resurrect_test.py | 7 +-- test/functional/mempool_spendcoinbase.py | 8 +-- test/functional/merkle_blocks.py | 11 ++-- test/functional/multi_rpc.py | 3 -- test/functional/net.py | 6 --- test/functional/nulldummy.py | 6 +-- test/functional/p2p-acceptblock.py | 8 +-- test/functional/p2p-compactblocks.py | 10 +--- test/functional/p2p-leaktests.py | 5 +- test/functional/p2p-mempool.py | 6 +-- test/functional/p2p-timeouts.py | 6 --- test/functional/p2p-versionbits-warning.py | 2 +- test/functional/preciousblock.py | 2 +- test/functional/prioritise_transaction.py | 11 +--- test/functional/proxy_test.py | 2 +- test/functional/pruning.py | 42 ++++++++------- test/functional/rawtransactions.py | 14 +---- test/functional/receivedby.py | 5 ++ test/functional/reindex.py | 3 -- test/functional/rest.py | 8 +-- test/functional/rpcnamedargs.py | 5 -- test/functional/sendheaders.py | 5 -- test/functional/signmessages.py | 4 -- test/functional/signrawtransactions.py | 4 -- test/functional/smartfees.py | 1 - .../test_framework/test_framework.py | 51 ++++++++----------- test/functional/test_framework/util.py | 15 +++++- test/functional/txn_clone.py | 4 +- test/functional/txn_doublespend.py | 4 +- test/functional/wallet-accounts.py | 6 +-- test/functional/wallet-hd.py | 17 ++----- test/functional/wallet.py | 3 +- test/functional/walletbackup.py | 4 +- test/functional/zapwallettxes.py | 8 +-- test/functional/zmq_test.py | 2 +- 62 files changed, 136 insertions(+), 342 deletions(-) diff --git a/test/functional/abandonconflict.py b/test/functional/abandonconflict.py index 887dbebd4f10..0439d168dead 100755 --- a/test/functional/abandonconflict.py +++ b/test/functional/abandonconflict.py @@ -20,12 +20,7 @@ def __init__(self): super().__init__() self.num_nodes = 2 self.setup_clean_chain = False - - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.00001"])) - self.nodes.append(start_node(1, self.options.tmpdir)) - connect_nodes(self.nodes[0], 1) + self.extra_args = [["-minrelaytxfee=0.00001"], []] def run_test(self): self.nodes[1].generate(100) diff --git a/test/functional/bip65-cltv-p2p.py b/test/functional/bip65-cltv-p2p.py index 107e8245f83e..7a4f43280bd1 100755 --- a/test/functional/bip65-cltv-p2p.py +++ b/test/functional/bip65-cltv-p2p.py @@ -38,12 +38,7 @@ class BIP65Test(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - - def setup_network(self): - # Must set the blockversion for this test - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1', '-blockversion=3']], - binary=[self.options.testbinary]) + self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=3']] def run_test(self): test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bip65-cltv.py b/test/functional/bip65-cltv.py index 7f13bb9952f1..ddf932c74606 100755 --- a/test/functional/bip65-cltv.py +++ b/test/functional/bip65-cltv.py @@ -12,15 +12,12 @@ def __init__(self): super().__init__() self.num_nodes = 3 self.setup_clean_chain = False + self.extra_args = [[], ["-blockversion=3"], ["-blockversion=4"]] def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, [])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=3"])) - self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=4"])) + self.setup_nodes() connect_nodes(self.nodes[1], 0) connect_nodes(self.nodes[2], 0) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/bip68-112-113-p2p.py b/test/functional/bip68-112-113-p2p.py index 7c01201bb58d..b0f045aa2a4f 100755 --- a/test/functional/bip68-112-113-p2p.py +++ b/test/functional/bip68-112-113-p2p.py @@ -95,14 +95,7 @@ class BIP68_112_113Test(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - - def setup_network(self): - # Must set the blockversion for this test - # Must also set '-maxtipage=600100' to allow syncing from very old blocks - # and '-dip3params=2000:2000' to create pre-dip3 blocks only - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1', '-blockversion=4', '-maxtipage=600100', '-dip3params=2000:2000']], - binary=[self.options.testbinary]) + self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-maxtipage=600100', '-dip3params=2000:2000']] def run_test(self): test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py index 408730f4919a..3386c8a022d8 100755 --- a/test/functional/bip68-sequence.py +++ b/test/functional/bip68-sequence.py @@ -21,16 +21,11 @@ def __init__(self): super().__init__() self.num_nodes = 2 self.setup_clean_chain = False + self.extra_args = [[], ["-acceptnonstdtxn=0"]] - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, [])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-acceptnonstdtxn=0"])) - self.is_network_split = False + def run_test(self): self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] - connect_nodes(self.nodes[0], 1) - def run_test(self): # Generate some coins self.nodes[0].generate(110) diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index 1175b1b7bce1..d98bc6d6e152 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -32,11 +32,7 @@ class BIP9SoftForksTest(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1']], - binary=[self.options.testbinary]) + self.extra_args = [['-whitelist=127.0.0.1']] def run_test(self): self.test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bipdersig-p2p.py b/test/functional/bipdersig-p2p.py index 5e7b1331b4c1..b4b352dac62b 100755 --- a/test/functional/bipdersig-p2p.py +++ b/test/functional/bipdersig-p2p.py @@ -46,12 +46,6 @@ def __init__(self): super().__init__() self.num_nodes = 1 - def setup_network(self): - # Must set the blockversion for this test - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1', '-blockversion=2']], - binary=[self.options.testbinary]) - def run_test(self): test = TestManager(self, self.options.tmpdir) test.add_all_connections(self.nodes) diff --git a/test/functional/bipdersig.py b/test/functional/bipdersig.py index 371cc41bb714..41f88fb664b2 100755 --- a/test/functional/bipdersig.py +++ b/test/functional/bipdersig.py @@ -12,15 +12,12 @@ def __init__(self): super().__init__() self.num_nodes = 3 self.setup_clean_chain = False + self.extra_args = [[], ["-blockversion=2"], ["-blockversion=3"]] def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, [])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=2"])) - self.nodes.append(start_node(2, self.options.tmpdir, ["-blockversion=3"])) + self.setup_nodes() connect_nodes(self.nodes[1], 0) connect_nodes(self.nodes[2], 0) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index a8a497a2383b..487b9ec12400 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -35,11 +35,6 @@ def __init__(self): self.setup_clean_chain = False self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - self.sync_all() - def run_test(self): self._test_gettxoutsetinfo() self._test_getblockheader() diff --git a/test/functional/decodescript.py b/test/functional/decodescript.py index 5555e96c4465..21a9f1223fd3 100755 --- a/test/functional/decodescript.py +++ b/test/functional/decodescript.py @@ -16,10 +16,6 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - def decodescript_script_sig(self): signature = '304502207fa7a6d1e0ee81132a269ad84e68d695483745cde8b541e3bf630749894e342a022100c1f7ab20e13e22fb95281a870f3dcf38d782e53023ee313d741ad0cfbc0c509001' push_signature = '48' + signature diff --git a/test/functional/disablewallet.py b/test/functional/disablewallet.py index 58bf373f0c1b..94d4402ea220 100755 --- a/test/functional/disablewallet.py +++ b/test/functional/disablewallet.py @@ -18,11 +18,7 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 - - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [['-disablewallet']]) - self.is_network_split = False - self.sync_all() + self.extra_args = [["-disablewallet"]] def run_test (self): # Check regression: https://github.com/bitcoin/bitcoin/issues/6963#issuecomment-154548880 diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py index 91d183618042..799bc50594fb 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/disconnect_ban.py @@ -23,10 +23,6 @@ def __init__(self): self.num_nodes = 2 self.setup_clean_chain = False - def setup_network(self): - self.nodes = self.setup_nodes() - connect_nodes_bi(self.nodes, 0, 1) - def run_test(self): self.log.info("Test setban and listbanned RPCs") diff --git a/test/functional/forknotify.py b/test/functional/forknotify.py index 7a365438cc24..9db61c8350f9 100755 --- a/test/functional/forknotify.py +++ b/test/functional/forknotify.py @@ -16,8 +16,6 @@ def __init__(self): self.num_nodes = 2 self.setup_clean_chain = False - alert_filename = None # Set by setup_network - def setup_network(self): self.nodes = [] self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") @@ -30,7 +28,6 @@ def setup_network(self): ["-blockversion=211"])) connect_nodes(self.nodes[1], 0) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index e5c145f3c30f..649c33d43195 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -23,15 +23,12 @@ def __init__(self): self.num_nodes = 4 def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [['-usehd=0']] * self.num_nodes) + self.setup_nodes([['-usehd=0']] * self.num_nodes) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - connect_nodes_bi(self.nodes,0,3) - - self.is_network_split=False - self.sync_all() + connect_nodes_bi(self.nodes, 0, 1) + connect_nodes_bi(self.nodes, 1, 2) + connect_nodes_bi(self.nodes, 0, 2) + connect_nodes_bi(self.nodes, 0, 3) def run_test(self): min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee'] @@ -467,7 +464,6 @@ def run_test(self): connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) connect_nodes_bi(self.nodes,0,3) - self.is_network_split=False self.sync_all() # drain the keypool diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 057b51afe1a8..4a6f5c283ad9 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -73,10 +73,6 @@ def __init__(self): self.num_nodes = 2 self.setup_clean_chain = False - def setup_network(self): - self.nodes = self.setup_nodes() - connect_nodes_bi(self.nodes, 0, 1) - def run_test(self): node = self.nodes[0] wait_to_sync(node) diff --git a/test/functional/getchaintips.py b/test/functional/getchaintips.py index 2dbc0f1d61c5..944c5b0640a9 100755 --- a/test/functional/getchaintips.py +++ b/test/functional/getchaintips.py @@ -31,7 +31,7 @@ def run_test (self): self.split_network () self.nodes[0].generate(10) self.nodes[2].generate(20) - self.sync_all () + self.sync_all([self.nodes[:2], self.nodes[2:]]) tips = self.nodes[1].getchaintips () assert_equal (len (tips), 1) diff --git a/test/functional/httpbasics.py b/test/functional/httpbasics.py index 8f35f0ab8799..4b32e8d9ca33 100755 --- a/test/functional/httpbasics.py +++ b/test/functional/httpbasics.py @@ -17,7 +17,7 @@ def __init__(self): self.setup_clean_chain = False def setup_network(self): - self.nodes = self.setup_nodes() + self.setup_nodes() def run_test(self): diff --git a/test/functional/importmulti.py b/test/functional/importmulti.py index e0493026329c..9e3491c428f5 100755 --- a/test/functional/importmulti.py +++ b/test/functional/importmulti.py @@ -12,9 +12,8 @@ def __init__(self): self.num_nodes = 2 self.setup_clean_chain = True - def setup_network(self, split=False): - self.nodes = start_nodes(2, self.options.tmpdir) - self.is_network_split=False + def setup_network(self): + self.setup_nodes() def run_test (self): self.log.info("Mining blocks...") diff --git a/test/functional/importprunedfunds.py b/test/functional/importprunedfunds.py index d9147da10b62..8f52b4d13bdc 100755 --- a/test/functional/importprunedfunds.py +++ b/test/functional/importprunedfunds.py @@ -14,12 +14,6 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 2 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes,0,1) - self.is_network_split=False - self.sync_all() - def run_test(self): self.log.info("Mining blocks...") self.nodes[0].generate(101) diff --git a/test/functional/invalidateblock.py b/test/functional/invalidateblock.py index 8c80b640035a..c499d57b9037 100755 --- a/test/functional/invalidateblock.py +++ b/test/functional/invalidateblock.py @@ -8,20 +8,15 @@ from test_framework.util import * class InvalidateTest(BitcoinTestFramework): - - + def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 3 def setup_network(self): - self.nodes = [] - self.is_network_split = False - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir)) - self.nodes.append(start_node(2, self.options.tmpdir)) - + self.setup_nodes() + def run_test(self): self.log.info("Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:") self.log.info("Mine 4 blocks on Node 0") diff --git a/test/functional/keypool.py b/test/functional/keypool.py index 2fdc39dbf72b..72f34d16b536 100755 --- a/test/functional/keypool.py +++ b/test/functional/keypool.py @@ -55,8 +55,5 @@ def run_test(self): nodes[0].generate(1) assert_raises_jsonrpc(-12, "Keypool ran out", nodes[0].generate, 1) - def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, [['-usehd=0']]) - if __name__ == '__main__': KeyPoolTest().main() diff --git a/test/functional/listsinceblock.py b/test/functional/listsinceblock.py index 852d6360e9d7..a73f72ba3358 100755 --- a/test/functional/listsinceblock.py +++ b/test/functional/listsinceblock.py @@ -43,7 +43,6 @@ def run_test (self): This test only checks that [tx0] is present. ''' - assert_equal(self.is_network_split, False) self.nodes[2].generate(101) self.sync_all() @@ -54,7 +53,6 @@ def run_test (self): # Split network into two self.split_network() - assert_equal(self.is_network_split, True) # send to nodes[0] from nodes[2] senttx = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 1) @@ -64,7 +62,7 @@ def run_test (self): self.nodes[2].generate(7) self.log.info('lastblockhash=%s' % (lastblockhash)) - self.sync_all() + self.sync_all([self.nodes[:2], self.nodes[2:]]) self.join_network() diff --git a/test/functional/listtransactions.py b/test/functional/listtransactions.py index 4ee332c64466..c4a466b8af4b 100755 --- a/test/functional/listtransactions.py +++ b/test/functional/listtransactions.py @@ -21,6 +21,11 @@ def __init__(self): self.num_nodes = 4 self.setup_clean_chain = False + def setup_nodes(self): + #This test requires mocktime + enable_mocktime() + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + def run_test(self): # Simple send, 0 to 1: txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1) diff --git a/test/functional/maxuploadtarget.py b/test/functional/maxuploadtarget.py index 82455cb0c40a..1a8f2d3b0555 100755 --- a/test/functional/maxuploadtarget.py +++ b/test/functional/maxuploadtarget.py @@ -35,15 +35,11 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 + self.extra_args = [["-maxuploadtarget=200", "-blockmaxsize=999000", "-maxtipage="+str(2*60*60*24*7)]] # Cache for utxos, as the listunspent may take a long time later in the test self.utxo_cache = [] - def setup_network(self): - # Start a node with maxuploadtarget of 200 MB (/24h) - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxuploadtarget=200", "-blockmaxsize=999000", "-maxtipage="+str(2*60*60*24*7)])) - def run_test(self): # Advance all nodes 2 weeks in the future old_mocktime = get_mocktime() diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py index aae9143fd6f6..cf800c82816b 100755 --- a/test/functional/mempool_limit.py +++ b/test/functional/mempool_limit.py @@ -9,30 +9,25 @@ class MempoolLimitTest(BitcoinTestFramework): - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxmempool=5", "-spendzeroconfchange=0"])) - self.is_network_split = False - self.sync_all() - self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] - def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 - - self.txouts = gen_return_txouts() + self.extra_args = [["-maxmempool=5", "-spendzeroconfchange=0"]] def run_test(self): + txouts = gen_return_txouts() + relayfee = self.nodes[0].getnetworkinfo()['relayfee'] + txids = [] - utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], 491) + utxos = create_confirmed_utxos(relayfee, self.nodes[0], 491) #create a mempool tx that will be evicted us0 = utxos.pop() inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}] outputs = {self.nodes[0].getnewaddress() : 0.0001} tx = self.nodes[0].createrawtransaction(inputs, outputs) - self.nodes[0].settxfee(self.relayfee) # specifically fund this tx with low fee + self.nodes[0].settxfee(relayfee) # specifically fund this tx with low fee txF = self.nodes[0].fundrawtransaction(tx) self.nodes[0].settxfee(0) # return to automatic fee selection txFS = self.nodes[0].signrawtransaction(txF['hex']) @@ -42,7 +37,7 @@ def run_test(self): base_fee = relayfee*100 for i in range (3): txids.append([]) - txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee) + txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee) # by now, the tx should be evicted, check confirmation state assert(txid not in self.nodes[0].getrawmempool()) diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py index feec8a7fd923..72f04095f47d 100755 --- a/test/functional/mempool_packages.py +++ b/test/functional/mempool_packages.py @@ -16,14 +16,7 @@ def __init__(self): super().__init__() self.num_nodes = 2 self.setup_clean_chain = False - - def setup_network(self): - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000"])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-maxorphantx=1000", "-limitancestorcount=5"])) - connect_nodes(self.nodes[0], 1) - self.is_network_split = False - self.sync_all() + self.extra_args = [["-maxorphantx=1000"], ["-maxorphantx=1000", "-limitancestorcount=5"]] # Build a transaction that spends parent_txid:vout # Return amount sent diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py index 07992e838222..4511ef4adcae 100755 --- a/test/functional/mempool_reorg.py +++ b/test/functional/mempool_reorg.py @@ -17,18 +17,10 @@ def __init__(self): super().__init__() self.num_nodes = 2 self.setup_clean_chain = False + self.extra_args = [["-checkmempool"]] * 2 alert_filename = None # Set by setup_network - def setup_network(self): - args = ["-checkmempool"] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.nodes.append(start_node(1, self.options.tmpdir, args)) - connect_nodes(self.nodes[1], 0) - self.is_network_split = False - self.sync_all() - def run_test(self): # Start with a 200 block chain assert_equal(self.nodes[0].getblockcount(), 200) diff --git a/test/functional/mempool_resurrect_test.py b/test/functional/mempool_resurrect_test.py index 7ff8bbea6fc2..1cb3b8269421 100755 --- a/test/functional/mempool_resurrect_test.py +++ b/test/functional/mempool_resurrect_test.py @@ -14,13 +14,8 @@ def __init__(self): super().__init__() self.num_nodes = 1 self.setup_clean_chain = False - - def setup_network(self): # Just need one node for this test - args = ["-checkmempool"] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.is_network_split = False + self.extra_args = [["-checkmempool"]] def run_test(self): node0_address = self.nodes[0].getnewaddress() diff --git a/test/functional/mempool_spendcoinbase.py b/test/functional/mempool_spendcoinbase.py index 1dbf8ae2581a..9780b31b22cc 100755 --- a/test/functional/mempool_spendcoinbase.py +++ b/test/functional/mempool_spendcoinbase.py @@ -22,13 +22,7 @@ def __init__(self): super().__init__() self.num_nodes = 1 self.setup_clean_chain = False - - def setup_network(self): - # Just need one node for this test - args = ["-checkmempool"] - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, args)) - self.is_network_split = False + self.extra_args = [["-checkmempool"]] def run_test(self): chain_height = self.nodes[0].getblockcount() diff --git a/test/functional/merkle_blocks.py b/test/functional/merkle_blocks.py index b5f6fcbd83ac..564a4b5b0130 100755 --- a/test/functional/merkle_blocks.py +++ b/test/functional/merkle_blocks.py @@ -13,20 +13,15 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 4 + # Nodes 0/1 are "wallet" nodes, Nodes 2/3 are used for testing + self.extra_args = [[], [], [], ["-txindex"]] def setup_network(self): - self.nodes = [] - # Nodes 0/1 are "wallet" nodes - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir)) - # Nodes 2/3 are used for testing - self.nodes.append(start_node(2, self.options.tmpdir)) - self.nodes.append(start_node(3, self.options.tmpdir, ["-txindex"])) + self.setup_nodes() connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 3) - self.is_network_split = False self.sync_all() def run_test(self): diff --git a/test/functional/multi_rpc.py b/test/functional/multi_rpc.py index 1179b406fca8..9e51810a8883 100755 --- a/test/functional/multi_rpc.py +++ b/test/functional/multi_rpc.py @@ -27,9 +27,6 @@ def setup_chain(self): f.write(rpcauth+"\n") f.write(rpcauth2+"\n") - def setup_network(self): - self.nodes = self.setup_nodes() - def run_test(self): ################################################## diff --git a/test/functional/net.py b/test/functional/net.py index 9eae14045502..16476f7d341c 100755 --- a/test/functional/net.py +++ b/test/functional/net.py @@ -25,12 +25,6 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 2 - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes, 0, 1) - self.is_network_split = False - self.sync_all() - def run_test(self): self._test_connection_count() self._test_getnettotals() diff --git a/test/functional/nulldummy.py b/test/functional/nulldummy.py index 3ad8a3235f31..81a29a1759e8 100755 --- a/test/functional/nulldummy.py +++ b/test/functional/nulldummy.py @@ -40,11 +40,7 @@ def __init__(self): super().__init__() self.num_nodes = 1 self.setup_clean_chain = True - - def setup_network(self): - # Must set the blockversion for this test - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1']]) + self.extra_args = [['-whitelist=127.0.0.1']] def run_test(self): self.address = self.nodes[0].getnewaddress() diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p-acceptblock.py index ebbc43dd1b4d..186bb0766939 100755 --- a/test/functional/p2p-acceptblock.py +++ b/test/functional/p2p-acceptblock.py @@ -64,17 +64,13 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 2 + self.extra_args = [[], ["-whitelist=127.0.0.1"]] def setup_network(self): # Node0 will be used to test behavior of processing unrequested blocks # from peers which are not whitelisted, while Node1 will be used for # the whitelisted case. - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, - binary=self.options.testbinary)) - self.nodes.append(start_node(1, self.options.tmpdir, - ["-whitelist=127.0.0.1"], - binary=self.options.testbinary)) + self.setup_nodes() def run_test(self): # Setup the p2p connections and start up the network thread. diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py index ed7e3feee637..f44db3538ebd 100755 --- a/test/functional/p2p-compactblocks.py +++ b/test/functional/p2p-compactblocks.py @@ -95,17 +95,9 @@ def __init__(self): self.setup_clean_chain = True # both nodes has the same version self.num_nodes = 2 + self.extra_args = [["-txindex"]] self.utxos = [] - def setup_network(self): - self.nodes = [] - - # Start up node0 to be a version 1, pre-segwit node. - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, - [["-txindex"], - ["-txindex"]]) - connect_nodes(self.nodes[0], 1) - def build_block_on_tip(self, node): height = node.getblockcount() tip = node.getbestblockhash() diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p-leaktests.py index 7c20614b18fe..0d2d4d190746 100755 --- a/test/functional/p2p-leaktests.py +++ b/test/functional/p2p-leaktests.py @@ -91,10 +91,7 @@ class P2PLeakTest(BitcoinTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - def setup_network(self): - extra_args = [['-banscore='+str(banscore)] - for i in range(self.num_nodes)] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.extra_args = [['-banscore='+str(banscore)]] def run_test(self): no_version_bannode = CNodeNoVersionBan() diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p-mempool.py index 188016e7184c..34ef249eeaa0 100755 --- a/test/functional/p2p-mempool.py +++ b/test/functional/p2p-mempool.py @@ -17,10 +17,8 @@ class P2PMempoolTests(BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True - self.num_nodes = 2 - - def setup_network(self): - self.nodes = [start_node(0, self.options.tmpdir, ["-peerbloomfilters=0"])] + self.num_nodes = 1 + self.extra_args = [["-peerbloomfilters=0"]] def run_test(self): #connect a mininode diff --git a/test/functional/p2p-timeouts.py b/test/functional/p2p-timeouts.py index 210e561e7436..c3b29c215b7d 100755 --- a/test/functional/p2p-timeouts.py +++ b/test/functional/p2p-timeouts.py @@ -38,12 +38,6 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self): - self.nodes = [] - - # Start up node0 to be a version 1, pre-segwit node. - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - def run_test(self): # Setup the p2p connections and start up the network thread. self.no_verack_node = TestNode() # never send verack diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py index 06cdd5f91d11..7254017e60f8 100755 --- a/test/functional/p2p-versionbits-warning.py +++ b/test/functional/p2p-versionbits-warning.py @@ -40,7 +40,7 @@ def setup_network(self): with open(self.alert_filename, 'w', encoding='utf8') as _: pass self.extra_args = [["-alertnotify=echo %s >> \"" + self.alert_filename + "\""]] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) + self.setup_nodes() # Send numblocks blocks via peer with nVersionToUse set. def send_blocks_with_version(self, peer, numblocks, nVersionToUse): diff --git a/test/functional/preciousblock.py b/test/functional/preciousblock.py index 65c4d6003033..bc728477a9c0 100755 --- a/test/functional/preciousblock.py +++ b/test/functional/preciousblock.py @@ -41,7 +41,7 @@ def __init__(self): self.num_nodes = 3 def setup_network(self): - self.nodes = self.setup_nodes() + self.setup_nodes() def run_test(self): self.log.info("Ensure submitblock can in principle reorg to a competing chain") diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py index 0da13e5ebd95..4258d201243c 100755 --- a/test/functional/prioritise_transaction.py +++ b/test/functional/prioritise_transaction.py @@ -14,19 +14,12 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 2 + self.extra_args = [["-printpriority=1"] * 2] + def run_test(self): self.txouts = gen_return_txouts() - - def setup_network(self): - self.nodes = [] - self.is_network_split = False - - self.nodes.append(start_node(0, self.options.tmpdir, ["-printpriority=1"])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-printpriority=1"])) # TODO move this to extra_args when Bitcoin #10198 gets backported - connect_nodes(self.nodes[0], 1) # TODO remove this when Bitcoin #10198 gets backported self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] - def run_test(self): utxo_count = 90 utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], utxo_count) base_fee = self.relayfee*100 # our transactions are smaller than 100kb diff --git a/test/functional/proxy_test.py b/test/functional/proxy_test.py index 748e3e69f681..69384d9d85af 100755 --- a/test/functional/proxy_test.py +++ b/test/functional/proxy_test.py @@ -90,7 +90,7 @@ def setup_nodes(self): ] if self.have_ipv6: args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] - return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) def node_test(self, node, proxies, auth, test_onion=True): rv = [] diff --git a/test/functional/pruning.py b/test/functional/pruning.py index 74a9ebb5a328..63dfeb59132e 100755 --- a/test/functional/pruning.py +++ b/test/functional/pruning.py @@ -32,31 +32,21 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 6 - # Cache for utxos, as the listunspent may take a long time later in the test - self.utxo_cache_0 = [] - self.utxo_cache_1 = [] - - def setup_network(self): - self.nodes = [] - self.is_network_split = False - - # Create nodes 0 and 1 to mine - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900)) - self.nodes.append(start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900)) - - # Create node 2 to test pruning - self.nodes.append(start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-maxreceivebuffer=20000","-prune=550"], redirect_stderr=True, timewait=900)) - self.prunedir = self.options.tmpdir+"/node2/regtest/blocks/" - + # Create nodes 0 and 1 to mine. + # Create node 2 to test pruning. # Create nodes 3 and 4 to test manual pruning (they will be re-started with manual pruning later) - self.nodes.append(start_node(3, self.options.tmpdir, ["-litemode","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], redirect_stderr=True, timewait=900)) - self.nodes.append(start_node(4, self.options.tmpdir, ["-litemode","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], redirect_stderr=True, timewait=900)) - # Create nodes 5 to test wallet in prune mode, but do not connect - self.nodes.append(start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], redirect_stderr=True)) + self.extra_args = [["-maxreceivebuffer=20000", "-blockmaxsize=999000", "-checkblocks=5"], + ["-maxreceivebuffer=20000", "-blockmaxsize=999000", "-checkblocks=5"], + ["-litemode","-txindex=0","-maxreceivebuffer=20000","-prune=550"], + ["-litemode","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], + ["-litemode","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], + ["-litemode","-txindex=0","-prune=550"]] - # Determine default relay fee - self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] + def setup_network(self): + self.setup_nodes() + + self.prunedir = self.options.tmpdir + "/node2/regtest/blocks/" connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[1], 2) @@ -332,6 +322,14 @@ def wallet_test(self): def run_test(self): self.log.info("Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours)") self.log.info("Mining a big blockchain of 995 blocks") + + # Determine default relay fee + self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"] + + # Cache for utxos, as the listunspent may take a long time later in the test + self.utxo_cache_0 = [] + self.utxo_cache_1 = [] + self.create_big_chain() # Chain diagram key: # * blocks on main chain diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py index b798b73db78b..fd9c7a81cbbd 100755 --- a/test/functional/rawtransactions.py +++ b/test/functional/rawtransactions.py @@ -24,21 +24,9 @@ def __init__(self): self.num_nodes = 3 def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - - #connect to a local machine for debugging - #url = "http://bitcoinrpc:DP6DvqZtqXarpeNWyN3LZTFchCCyCUuHwNF7E8pX99x1@%s:%d" % ('127.0.0.1', 18332) - #proxy = AuthServiceProxy(url) - #proxy.url = url # store URL on proxy for info - #self.nodes.append(proxy) - - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) + super().setup_network() connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() - def run_test(self): #prepare some coins for multiple *rawtransaction commands diff --git a/test/functional/receivedby.py b/test/functional/receivedby.py index bb399f02e07d..b0d94741573a 100755 --- a/test/functional/receivedby.py +++ b/test/functional/receivedby.py @@ -29,6 +29,11 @@ def __init__(self): self.num_nodes = 4 self.setup_clean_chain = False + def setup_nodes(self): + #This test requires mocktime + enable_mocktime() + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + def run_test(self): ''' listreceivedbyaddress Test diff --git a/test/functional/reindex.py b/test/functional/reindex.py index 0cebb0466f72..8b8c5f3e710a 100755 --- a/test/functional/reindex.py +++ b/test/functional/reindex.py @@ -24,9 +24,6 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - def reindex(self, justchainstate=False): self.nodes[0].generate(3) blockcount = self.nodes[0].getblockcount() diff --git a/test/functional/rest.py b/test/functional/rest.py index b3519f0987d3..cf46434f65fa 100755 --- a/test/functional/rest.py +++ b/test/functional/rest.py @@ -49,12 +49,8 @@ def __init__(self): self.num_nodes = 3 def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) - connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() + super().setup_network() + connect_nodes_bi(self.nodes, 0, 2) def run_test(self): url = urllib.parse.urlparse(self.nodes[0].url) diff --git a/test/functional/rpcnamedargs.py b/test/functional/rpcnamedargs.py index f6175c8ca7c2..fd81b02ead17 100755 --- a/test/functional/rpcnamedargs.py +++ b/test/functional/rpcnamedargs.py @@ -22,11 +22,6 @@ def __init__(self): self.setup_clean_chain = False self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - self.sync_all() - def run_test(self): node = self.nodes[0] h = node.help(command='getinfo') diff --git a/test/functional/sendheaders.py b/test/functional/sendheaders.py index 72cddb91ccaa..0d0fcfe96d0c 100755 --- a/test/functional/sendheaders.py +++ b/test/functional/sendheaders.py @@ -193,11 +193,6 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 2 - def setup_network(self): - self.nodes = [] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes(self.nodes[0], 1) - # mine count blocks and return the new tip def mine_blocks(self, count): # Clear out last block announcement from each p2p listener diff --git a/test/functional/signmessages.py b/test/functional/signmessages.py index df2c819673b0..d9b16ff3c17d 100755 --- a/test/functional/signmessages.py +++ b/test/functional/signmessages.py @@ -14,10 +14,6 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - def run_test(self): message = 'This is just a test message' diff --git a/test/functional/signrawtransactions.py b/test/functional/signrawtransactions.py index a2ebdcebb9d7..e66d2e310f9d 100755 --- a/test/functional/signrawtransactions.py +++ b/test/functional/signrawtransactions.py @@ -14,10 +14,6 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 1 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - def successful_signing_test(self): """Create and sign a valid raw transaction with one input. diff --git a/test/functional/smartfees.py b/test/functional/smartfees.py index 921178925f2c..72d00f9acb3d 100755 --- a/test/functional/smartfees.py +++ b/test/functional/smartfees.py @@ -204,7 +204,6 @@ def setup_network(self): connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[2], 1) - self.is_network_split = False self.sync_all() def transact_and_mine(self, numblocks, mining_node): diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 82d69b10162c..1ee436647477 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -21,6 +21,7 @@ start_nodes, connect_nodes_bi, connect_nodes, + disconnect_nodes, sync_blocks, sync_mempools, sync_masternodes, @@ -71,52 +72,42 @@ def stop_node(self, num_node): stop_node(self.nodes[num_node], num_node) def setup_nodes(self): - return start_nodes(self.num_nodes, self.options.tmpdir) + extra_args = None + if hasattr(self, "extra_args"): + extra_args = self.extra_args + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) - def setup_network(self, split = False): - self.nodes = self.setup_nodes() + def setup_network(self): + self.setup_nodes() # Connect the nodes as a "chain". This allows us # to split the network between nodes 1 and 2 to get # two halves that can work on competing chains. - - # If we joined network halves, connect the nodes from the joint - # on outward. This ensures that chains are properly reorganised. - if not split: - connect_nodes_bi(self.nodes, 1, 2) - sync_blocks(self.nodes[1:3]) - sync_mempools(self.nodes[1:3]) - - connect_nodes_bi(self.nodes, 0, 1) - connect_nodes_bi(self.nodes, 2, 3) - self.is_network_split = split + for i in range(self.num_nodes - 1): + connect_nodes_bi(self.nodes, i, i + 1) self.sync_all() def split_network(self): """ Split the network of four nodes into nodes 0/1 and 2/3. """ - assert not self.is_network_split - stop_nodes(self.nodes) - self.setup_network(True) - - def sync_all(self): - if self.is_network_split: - sync_blocks(self.nodes[:2]) - sync_blocks(self.nodes[2:]) - sync_mempools(self.nodes[:2]) - sync_mempools(self.nodes[2:]) - else: - sync_blocks(self.nodes) - sync_mempools(self.nodes) + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) + self.sync_all([self.nodes[:2], self.nodes[2:]]) + + def sync_all(self, node_groups=None): + if not node_groups: + node_groups = [self.nodes] + + [sync_blocks(group) for group in node_groups] + [sync_mempools(group) for group in node_groups] def join_network(self): """ Join the (previously split) network halves together. """ - assert self.is_network_split - stop_nodes(self.nodes) - self.setup_network(False) + connect_nodes_bi(self.nodes, 1, 2) + self.sync_all() def main(self): diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 2264184e2a3c..6ef206df2f4d 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -343,7 +343,7 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= if binary is None: binary = os.getenv("BITCOIND", "dashd") # RPC tests still depend on free transactions - args = [binary, "-datadir=" + datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(get_mocktime())] + args = [binary, "-datadir=" + datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(get_mocktime()), "-uacomment=testnode%d" % i] # Don't try auto backups (they fail a lot when running tests) args += [ "-createwalletbackups=0" ] if extra_args is not None: args.extend(extra_args) @@ -390,6 +390,8 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None """ if extra_args is None: extra_args = [ None for _ in range(num_nodes) ] if binary is None: binary = [ None for _ in range(num_nodes) ] + assert_equal(len(extra_args), num_nodes) + assert_equal(len(binary), num_nodes) rpcs = [] try: for i in range(num_nodes): @@ -443,6 +445,17 @@ def set_node_times(nodes, t): for node in nodes: node.setmocktime(t) +def disconnect_nodes(from_connection, node_num): + for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]: + from_connection.disconnectnode(nodeid=peer_id) + + for _ in range(50): + if [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == []: + break + time.sleep(0.1) + else: + raise AssertionError("timed out waiting for disconnect") + def connect_nodes(from_connection, node_num): ip_port = "127.0.0.1:"+str(p2p_port(node_num)) from_connection.addnode(ip_port, "onetry") diff --git a/test/functional/txn_clone.py b/test/functional/txn_clone.py index 41e2865bc993..fd28ff4b1bf8 100755 --- a/test/functional/txn_clone.py +++ b/test/functional/txn_clone.py @@ -20,7 +20,9 @@ def add_options(self, parser): def setup_network(self): # Start with split network: - return super(TxnMallTest, self).setup_network(True) + super(TxnMallTest, self).setup_network() + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) def run_test(self): # All nodes should start with 12,500 DASH: diff --git a/test/functional/txn_doublespend.py b/test/functional/txn_doublespend.py index 8ea9cd435e46..197d3b915de9 100755 --- a/test/functional/txn_doublespend.py +++ b/test/functional/txn_doublespend.py @@ -20,7 +20,9 @@ def add_options(self, parser): def setup_network(self): # Start with split network: - return super(TxnMallTest, self).setup_network(True) + super().setup_network() + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) def run_test(self): # All nodes should start with 12,500 DASH: diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py index 11b295f2238e..1a97403fdbbd 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet-accounts.py @@ -24,11 +24,7 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 - self.node_args = [[]] - - def setup_network(self): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.node_args) - self.is_network_split = False + self.extra_args = [[]] def run_test (self): node = self.nodes[0] diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index 0df5335294ae..b68434f5aa54 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -13,14 +13,7 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 2 - self.node_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']] - - def setup_network(self): - self.nodes = start_nodes(2, self.options.tmpdir, self.node_args, redirect_stderr=True) - self.is_network_split = False - connect_nodes_bi(self.nodes, 0, 1) - self.is_network_split=False - self.sync_all() + self.extra_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']] def run_test (self): tmpdir = self.options.tmpdir @@ -28,7 +21,7 @@ def run_test (self): # Make sure can't switch off usehd after wallet creation self.stop_node(1) assert_start_raises_init_error(1, self.options.tmpdir, ['-usehd=0'], 'already existing HD wallet') - self.nodes[1] = start_node(1, self.options.tmpdir, self.node_args[1], redirect_stderr=True) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1], redirect_stderr=True) connect_nodes_bi(self.nodes, 0, 1) # Make sure we use hd, keep chainid @@ -75,7 +68,7 @@ def run_test (self): stop_node(self.nodes[1],1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") - self.nodes[1] = start_node(1, self.options.tmpdir, ['-usehd=1', '-keypool=0'], redirect_stderr=True) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1], redirect_stderr=True) #connect_nodes_bi(self.nodes, 0, 1) # Assert that derivation is deterministic @@ -88,8 +81,8 @@ def run_test (self): assert_equal(hd_add, hd_add_2) # Needs rescan - stop_node(self.nodes[1],1) - self.nodes[1] = start_node(1, self.options.tmpdir, ['-usehd=1', '-keypool=0', '-rescan'], redirect_stderr=True) + self.stop_node(1) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan']) #connect_nodes_bi(self.nodes, 0, 1) assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) diff --git a/test/functional/wallet.py b/test/functional/wallet.py index 8a6637663e94..8ad41a58e42b 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -20,12 +20,11 @@ def __init__(self): self.num_nodes = 4 self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)] - def setup_network(self, split=False): + def setup_network(self): self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3], redirect_stderr=True) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False self.sync_all() def run_test(self): diff --git a/test/functional/walletbackup.py b/test/functional/walletbackup.py index 65331a707e62..2ecd7ee19f93 100755 --- a/test/functional/walletbackup.py +++ b/test/functional/walletbackup.py @@ -44,14 +44,12 @@ def __init__(self): # nodes 1, 2,3 are spenders, let's give them a keypool=100 self.extra_args = [["-keypool=100"], ["-keypool=100"], ["-keypool=100"], []] - # This mirrors how the network was setup in the bash test def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) + self.setup_nodes() connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[1], 3) connect_nodes(self.nodes[2], 3) connect_nodes(self.nodes[2], 0) - self.is_network_split=False self.sync_all() def one_send(self, from_node, to_address): diff --git a/test/functional/zapwallettxes.py b/test/functional/zapwallettxes.py index bcb201648f3b..bd5f024d6578 100755 --- a/test/functional/zapwallettxes.py +++ b/test/functional/zapwallettxes.py @@ -23,13 +23,9 @@ def __init__(self): self.setup_clean_chain = True self.num_nodes = 3 - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - connect_nodes_bi(self.nodes,0,1) - connect_nodes_bi(self.nodes,1,2) + def setup_network(self): + super().setup_network() connect_nodes_bi(self.nodes,0,2) - self.is_network_split=False - self.sync_all() def run_test (self): self.log.info("Mining blocks...") diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index fdcb0f0e89d7..43861c767bab 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -40,7 +40,7 @@ def setup_nodes(self): self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx") self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port) - return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ ['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)], [], [], From 52de8b11d57c01e5e876cc65516310c6dd0a7c3f Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 2 May 2017 20:18:30 +0200 Subject: [PATCH 205/987] Merge #10255: [test] Add test for listaddressgroupings dadfee3 [test] Add test for listaddressgroupings (Jimmy Song) Tree-SHA512: 21cf0233c7fcf585f9a31306612ae1113ea916d2972b834efef0cb2154bd4dd24d9746d0632c778c699328f7e7a336d2da6e2bac9f0fb657c30290757563ad22 --- test/functional/wallet-accounts.py | 60 +++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py index 1a97403fdbbd..50f852b2f20f 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet-accounts.py @@ -7,6 +7,7 @@ RPCs tested are: - getaccountaddress - getaddressesbyaccount + - listaddressgroupings - setaccount - sendfrom (with account arguments) - move (with account arguments) @@ -26,16 +27,57 @@ def __init__(self): self.num_nodes = 1 self.extra_args = [[]] - def run_test (self): + def run_test(self): node = self.nodes[0] # Check that there's no UTXO on any of the nodes assert_equal(len(node.listunspent()), 0) - + + # Note each time we call generate, all generated coins go into + # the same address, so we call twice to get two addresses w/50 each + node.generate(1) node.generate(101) - - assert_equal(node.getbalance(), 500) - - accounts = ["a","b","c","d","e"] + assert_equal(node.getbalance(), 1000) + + # there should be 2 address groups + # each with 1 address with a balance of 500 Dash + address_groups = node.listaddressgroupings() + assert_equal(len(address_groups), 2) + # the addresses aren't linked now, but will be after we send to the + # common address + linked_addresses = set() + for address_group in address_groups: + assert_equal(len(address_group), 1) + assert_equal(len(address_group[0]), 2) + assert_equal(address_group[0][1], 500) + linked_addresses.add(address_group[0][0]) + + # send 500 from each address to a third address not in this wallet + # There's some fee that will come back to us when the miner reward + # matures. + common_address = "msf4WtN1YQKXvNtvdFYt9JBnUD2FB41kjr" + txid = node.sendmany( + fromaccount="", + amounts={common_address: 100}, + subtractfeefrom=[common_address], + minconf=1, + ) + tx_details = node.gettransaction(txid) + fee = -tx_details['details'][0]['fee'] + # there should be 1 address group, with the previously + # unlinked addresses now linked (they both have 0 balance) + address_groups = node.listaddressgroupings() + assert_equal(len(address_groups), 1) + assert_equal(len(address_groups[0]), 2) + assert_equal(set([a[0] for a in address_groups[0]]), linked_addresses) + assert_equal([a[1] for a in address_groups[0]], [0, 0]) + + node.generate(1) + + # we want to reset so that the "" account has what's expected. + # otherwise we're off by exactly the fee amount as that's mined + # and matures in the next 100 blocks + node.sendfrom("", common_address, fee) + accounts = ["a", "b", "c", "d", "e"] amount_to_send = 1.0 account_addresses = dict() for account in accounts: @@ -52,7 +94,7 @@ def run_test (self): for i in range(len(accounts)): from_account = accounts[i] - to_account = accounts[(i+1)%len(accounts)] + to_account = accounts[(i+1) % len(accounts)] to_address = account_addresses[to_account] node.sendfrom(from_account, to_address, amount_to_send) @@ -63,7 +105,7 @@ def run_test (self): assert(address != account_addresses[account]) assert_equal(node.getreceivedbyaccount(account), 2) node.move(account, "", node.getbalance(account)) - + node.generate(101) expected_account_balances = {"": 52000} @@ -93,4 +135,4 @@ def run_test (self): assert_equal(node.getbalance(account), 50) if __name__ == '__main__': - WalletAccountsTest().main () + WalletAccountsTest().main() From 94195342495bfba5e28ccdd15068c335e28fee37 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 2 May 2017 20:50:57 +0200 Subject: [PATCH 206/987] Merge #10137: Remove unused import. Remove accidental trailing semicolons. 73b3721 Remove accidental trailing semicolons (practicalswift) b8d9a86 Remove unused import (practicalswift) Tree-SHA512: 36ac38952f8a10f36d2300519c583ef77703cff761be97470be97cfda2fec9d5b7ac604e454f174cc2601160e5cef3f227021ab5d3a6febc97fcb486d78754d3 --- test/functional/bip9-softforks.py | 1 - test/functional/p2p-versionbits-warning.py | 1 - test/functional/wallet-hd.py | 6 +++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index d98bc6d6e152..da7d1efa5dcc 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -16,7 +16,6 @@ test that enforcement has triggered """ -from test_framework.blockstore import BlockStore from test_framework.test_framework import ComparisonTestFramework from test_framework.util import * from test_framework.mininode import CTransaction, NetworkThread diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py index 7254017e60f8..41921fe14e3c 100755 --- a/test/functional/p2p-versionbits-warning.py +++ b/test/functional/p2p-versionbits-warning.py @@ -12,7 +12,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * import re -import time from test_framework.blocktools import create_block, create_coinbase VB_PERIOD = 144 # versionbits period length for regtest diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index b68434f5aa54..6d0955e5606a 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -30,7 +30,7 @@ def run_test (self): # create an internal key change_addr = self.nodes[1].getrawchangeaddress() - change_addrV= self.nodes[1].validateaddress(change_addr); + change_addrV= self.nodes[1].validateaddress(change_addr) assert_equal(change_addrV["hdkeypath"], "m/44'/1'/0'/1/0") #first internal child key # Import a non-HD private key in the HD wallet @@ -58,7 +58,7 @@ def run_test (self): # create an internal key (again) change_addr = self.nodes[1].getrawchangeaddress() - change_addrV= self.nodes[1].validateaddress(change_addr); + change_addrV= self.nodes[1].validateaddress(change_addr) assert_equal(change_addrV["hdkeypath"], "m/44'/1'/0'/1/1") #second internal child key self.sync_all() @@ -88,7 +88,7 @@ def run_test (self): # send a tx and make sure its using the internal chain for the changeoutput txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) - outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout']; + outs = self.nodes[1].decoderawtransaction(self.nodes[1].gettransaction(txid)['hex'])['vout'] keypath = "" for out in outs: if out['value'] != 1: From 6f741e5583a1085ef1ab89193e8a066c5f56b56b Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 3 May 2017 08:14:50 +0200 Subject: [PATCH 207/987] Merge #9733: Add getchaintxstats RPC bd1f138 Add getchaintxstats RPC (Pieter Wuille) Tree-SHA512: 270785b25e7e2faad4528b5ef591d9dc6266f15236563e3f02dac1f2d9ce3732c4d44903fcccf38549f7921f29d1a93cb0a118b7453ccc5afd79739b51e68f46 --- src/rpc/blockchain.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++ src/rpc/client.cpp | 1 + 2 files changed, 67 insertions(+) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 7df8fb3f5ab6..90f8e005d098 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1727,6 +1727,71 @@ UniValue reconsiderblock(const JSONRPCRequest& request) return NullUniValue; } +UniValue getchaintxstats(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() > 2) + throw std::runtime_error( + "getchaintxstats ( nblocks blockhash )\n" + "\nCompute statistics about the total number and rate of transactions in the chain.\n" + "\nArguments:\n" + "1. nblocks (numeric, optional) Size of the window in number of blocks (default: one month).\n" + "2. \"blockhash\" (string, optional) The hash of the block that ends the window.\n" + "\nResult:\n" + "{\n" + " \"time\": xxxxx, (numeric) The timestamp for the statistics in UNIX format.\n" + " \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n" + " \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window.\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getchaintxstats", "") + + HelpExampleRpc("getchaintxstats", "2016") + ); + + const CBlockIndex* pindex; + int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month + + if (request.params.size() > 0 && !request.params[0].isNull()) { + blockcount = request.params[0].get_int(); + } + + bool havehash = request.params.size() > 1 && !request.params[1].isNull(); + uint256 hash; + if (havehash) { + hash = uint256S(request.params[1].get_str()); + } + + { + LOCK(cs_main); + if (havehash) { + auto it = mapBlockIndex.find(hash); + if (it == mapBlockIndex.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + } + pindex = it->second; + if (!chainActive.Contains(pindex)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain"); + } + } else { + pindex = chainActive.Tip(); + } + } + + if (blockcount < 1 || blockcount >= pindex->nHeight) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height"); + } + + const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount); + int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast(); + int nTxDiff = pindex->nChainTx - pindexPast->nChainTx; + + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("time", (int64_t)pindex->nTime)); + ret.push_back(Pair("txcount", (int64_t)pindex->nChainTx)); + ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff)); + + return ret; +} + UniValue getspecialtxes(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 1 || request.params.size() > 5) @@ -1838,6 +1903,7 @@ static const CRPCCommand commands[] = { // category name actor (function) okSafe argNames // --------------------- ------------------------ ----------------------- ------ ---------- { "blockchain", "getblockchaininfo", &getblockchaininfo, true, {} }, + { "blockchain", "getchaintxstats", &getchaintxstats, true, {"nblocks", "blockhash"} }, { "blockchain", "getbestblockhash", &getbestblockhash, true, {} }, { "blockchain", "getblockcount", &getblockcount, true, {} }, { "blockchain", "getblock", &getblock, true, {"blockhash","verbosity|verbose"} }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 03cdd9cda11a..05455a032b33 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -103,6 +103,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getblockheader", 1, "verbose" }, { "getblockheaders", 1, "count" }, { "getblockheaders", 2, "verbose" }, + { "getchaintxstats", 0, "nblocks" }, { "getmerkleblocks", 2, "count" }, { "gettransaction", 1, "include_watchonly" }, { "getrawtransaction", 1, "verbose" }, From 3d87faff5e792acf34e90548074916acf409aeea Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 3 May 2017 08:37:14 +0200 Subject: [PATCH 208/987] Merge #10307: [tests] allow zmq test to be run in out-of-tree builds b8251f6 [tests] allow zmq test to be run in out-of-tree builds (John Newbery) Tree-SHA512: 6946d23bc8a0b57e841a6811989182732d0534989e0e3b94421387f7971379b25a25d238cad22272e04076293275f6e980c8a713fce87ba48c1c4463d9243051 --- test/functional/test_framework/test_framework.py | 2 ++ test/functional/test_runner.py | 5 ++++- test/functional/zmq_test.py | 6 ++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 1ee436647477..648e790a02e8 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -130,6 +130,8 @@ def main(self): help="The seed to use for assigning port numbers (default: current process id)") parser.add_option("--coveragedir", dest="coveragedir", help="Write tested RPC commands into this directory") + parser.add_option("--configfile", dest="configfile", + help="Location of the test framework config file") self.add_options(parser) (self.options, self.args) = parser.parse_args() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 6bcdd629e191..ce6831d890ff 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -192,7 +192,10 @@ def main(): # Read config generated by configure. config = configparser.ConfigParser() - config.read_file(open(os.path.dirname(__file__) + "/config.ini")) + configfile = os.path.abspath(os.path.dirname(__file__)) + "/config.ini" + config.read_file(open(configfile)) + + passon_args.append("--configfile=%s" % configfile) # Set up logging logging_level = logging.INFO if args.quiet else logging.DEBUG diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index 43861c767bab..fe7d7aa87d90 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -27,9 +27,11 @@ def setup_nodes(self): self.log.warning("python3-zmq module not available. Skipping zmq tests!") sys.exit(self.TEST_EXIT_SKIPPED) - # Check that bitcoin has been built with ZMQ enabled + # Check that dash has been built with ZMQ enabled config = configparser.ConfigParser() - config.read_file(open(os.path.dirname(__file__) + "/config.ini")) + if not self.options.configfile: + self.options.configfile = os.path.dirname(__file__) + "/config.ini" + config.read_file(open(self.options.configfile)) if not config["components"].getboolean("ENABLE_ZMQ"): self.log.warning("dashd has not been built with zmq enabled. Skipping zmq tests!") From 80f8bb17ddf8867157695f3229874c4a054c4020 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 3 May 2017 09:23:39 +0200 Subject: [PATCH 209/987] Merge #9966: Control mempool persistence using a command line parameter a750d77 Add tests for mempool persistence (John Newbery) 91c91e1 Control mempool persistence using a command line parameter. (John Newbery) Tree-SHA512: 157d01cefd1903b8bfc5cbab42a3cc5e9c1094179bf4b64b3d34c0d4d9b976d593755bfea5c41c631cb758e1de17c6c2058c130d487d20560b7c0bafcddfa520 --- src/init.cpp | 10 +++- src/validation.h | 2 + test/functional/mempool_persist.py | 91 ++++++++++++++++++++++++++++++ test/functional/test_runner.py | 1 + 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100755 test/functional/mempool_persist.py diff --git a/src/init.cpp b/src/init.cpp index 05b511090874..20d2ff78f84b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -280,8 +280,9 @@ void PrepareShutdown() } UnregisterNodeSignals(GetNodeSignals()); - if (fDumpMempoolLater) + if (fDumpMempoolLater && GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { DumpMempool(); + } if (fFeeEstimatesInitialized) { @@ -462,6 +463,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-maxorphantx=", strprintf(_("Keep at most unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS)); strUsage += HelpMessageOpt("-maxmempool=", strprintf(_("Keep the transaction memory pool below megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE)); strUsage += HelpMessageOpt("-mempoolexpiry=", strprintf(_("Do not keep transactions in the mempool longer than hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY)); + strUsage += HelpMessageOpt("-persistmempool", strprintf(_("Whether to save the mempool on shutdown and load on restart (default: %u)"), DEFAULT_PERSIST_MEMPOOL)); strUsage += HelpMessageOpt("-blockreconstructionextratxn=", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN)); strUsage += HelpMessageOpt("-par=", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"), -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS)); @@ -843,8 +845,10 @@ void ThreadImport(std::vector vImportFiles) } #endif - LoadMempool(); - fDumpMempoolLater = !fRequestShutdown; + if (GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { + LoadMempool(); + fDumpMempoolLater = !fRequestShutdown; + } } /** Sanity checks diff --git a/src/validation.h b/src/validation.h index a419cca55133..1982f0d12c49 100644 --- a/src/validation.h +++ b/src/validation.h @@ -138,6 +138,8 @@ static const bool DEFAULT_ADDRESSINDEX = false; static const bool DEFAULT_TIMESTAMPINDEX = false; static const bool DEFAULT_SPENTINDEX = false; static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100; +/** Default for -persistmempool */ +static const bool DEFAULT_PERSIST_MEMPOOL = true; /** Maximum number of headers to announce when relaying blocks with headers message.*/ static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8; diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py new file mode 100755 index 000000000000..c22b7ff0200a --- /dev/null +++ b/test/functional/mempool_persist.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test mempool persistence. + +By default, bitcoind will dump mempool on shutdown and +then reload it on startup. This can be overridden with +the -persistmempool=false command line option. + +Test is as follows: + + - start node0, node1 and node2. node1 has -persistmempool=false + - create 5 transactions on node2 to its own address. Note that these + are not sent to node0 or node1 addresses because we don't want + them to be saved in the wallet. + - check that node0 and node1 have 5 transactions in their mempools + - shutdown all nodes. + - startup node0. Verify that it still has 5 transactions + in its mempool. Shutdown node0. This tests that by default the + mempool is persistent. + - startup node1. Verify that its mempool is empty. Shutdown node1. + This tests that with -persistmempool=false, the mempool is not + dumped to disk when the node is shut down. + - Restart node0 with -persistmempool=false. Verify that its mempool is + empty. Shutdown node0. This tests that with -persistmempool=false, + the mempool is not loaded from disk on start up. + - Restart node0 with -persistmempool=true. Verify that it has 5 + transactions in its mempool. This tests that -persistmempool=false + does not overwrite a previously valid mempool stored on disk. + +""" + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * + +class MempoolPersistTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.num_nodes = 3 + self.setup_clean_chain = False + + def setup_network(self): + # We need 3 nodes for this test. Node1 does not have a persistent mempool. + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir)) + self.nodes.append(start_node(1, self.options.tmpdir, ["-persistmempool=false"])) + self.nodes.append(start_node(2, self.options.tmpdir)) + connect_nodes_bi(self.nodes, 0, 2) + connect_nodes_bi(self.nodes, 1, 2) + self.is_network_split = False + + def run_test(self): + chain_height = self.nodes[0].getblockcount() + assert_equal(chain_height, 200) + + self.log.debug("Mine a single block to get out of IBD") + self.nodes[0].generate(1) + + self.log.debug("Send 5 transactions from node2 (to its own address)") + for i in range(5): + self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), Decimal("10")) + self.sync_all() + + self.log.debug("Verify that node0 and node1 have 5 transactions in their mempools") + assert_equal(len(self.nodes[0].getrawmempool()), 5) + assert_equal(len(self.nodes[1].getrawmempool()), 5) + + self.log.debug("Stop-start node0 and node1. Verify that node0 has the transactions in its mempool and node1 does not.") + stop_nodes(self.nodes) + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir)) + self.nodes.append(start_node(1, self.options.tmpdir)) + assert_equal(len(self.nodes[0].getrawmempool()), 5) + assert_equal(len(self.nodes[1].getrawmempool()), 0) + + self.log.debug("Stop-start node0 with -persistmempool=false. Verify that it doesn't load its mempool.dat file.") + stop_nodes(self.nodes) + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=false"])) + assert_equal(len(self.nodes[0].getrawmempool()), 0) + + self.log.debug("Stop-start node0. Verify that it has the transactions in its mempool.") + stop_nodes(self.nodes) + self.nodes = [] + self.nodes.append(start_node(0, self.options.tmpdir)) + assert_equal(len(self.nodes[0].getrawmempool()), 5) + +if __name__ == '__main__': + MempoolPersistTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index ce6831d890ff..6187ddf4013b 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -94,6 +94,7 @@ 'rest.py', 'mempool_spendcoinbase.py', 'mempool_reorg.py', + 'mempool_persist.py', 'httpbasics.py', 'multi_rpc.py', 'proxy_test.py', From d4e6ab341b60a87d4b25c6a90924237c404b55df Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 3 May 2017 11:36:20 +0200 Subject: [PATCH 210/987] Merge #10302: [Makefile] Alphabetically Reorder addrdb.cpp 56f09df [Makefile] Alphabetically Reorder addrdb.cpp (Spencer Lievens) Tree-SHA512: cedf64f5b4a6b20c07881f7e9c1c36421ee04a1ba17319946bae0197f9475dba6d5bda05f8f5d72539fbffcaa0adf8f474ecb2089106215c996576ab1235e8e1 --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index c374d6f03eb3..e3a08b6125fc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -260,8 +260,8 @@ libdash_util_a-clientversion.$(OBJEXT): obj/build.h libdash_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libdash_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libdash_server_a_SOURCES = \ - addrman.cpp \ addrdb.cpp \ + addrman.cpp \ alert.cpp \ batchedlogger.cpp \ bloom.cpp \ From 14fbe9954a9be83b1aebe6a6f2e7612944c0e559 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 3 May 2017 15:42:24 +0200 Subject: [PATCH 211/987] Merge #10327: [tests] remove import-abort-rescan.py 981e586 [tests] remove import-abort-rescan.py (John Newbery) Tree-SHA512: 8658d42b5ecdefbb71c55849036ee4e8e113abbc9c549730524009fb6eacc50340ffb7ef99fb35809d4abd6b304d491a618e45ff6ded1990f01f18cbcebf2b12 --- test/functional/import-abort-rescan.py | 66 -------------------------- test/functional/test_runner.py | 1 - 2 files changed, 67 deletions(-) delete mode 100755 test/functional/import-abort-rescan.py diff --git a/test/functional/import-abort-rescan.py b/test/functional/import-abort-rescan.py deleted file mode 100755 index ffe45bbb1df6..000000000000 --- a/test/functional/import-abort-rescan.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2017 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test wallet import RPCs. - -Test rescan behavior of importprivkey when aborted. The test ensures that: -1. The abortrescan command indeed stops the rescan process. -2. Subsequent rescan catches the aborted address UTXO -""" - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import (assert_equal, get_rpc_proxy) -from decimal import Decimal -import threading # for bg importprivkey -import time # for sleep - -class ImportAbortRescanTest(BitcoinTestFramework): - def __init__(self): - super().__init__() - self.setup_clean_chain = True - - def run_test(self): - # Generate for BTC - assert_equal(self.nodes[0].getbalance(), 0) - assert_equal(self.nodes[1].getbalance(), 0) - self.nodes[0].generate(300) - assert_equal(self.nodes[1].getbalance(), 0) - # Make blocks with spam to cause rescan delay - for i in range(5): - for j in range(5): - self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.1) - self.nodes[0].generate(10) - addr = self.nodes[0].getnewaddress() - privkey = self.nodes[0].dumpprivkey(addr) - self.nodes[0].sendtoaddress(addr, 0.123) - self.nodes[0].generate(10) # mature tx - self.sync_all() - - # Import this address in the background ... - node1ref = get_rpc_proxy(self.nodes[1].url, 1, timeout=600) - importthread = threading.Thread(target=node1ref.importprivkey, args=[privkey]) - importthread.start() - # ... then abort rescan; try a bunch until abortres becomes true, - # because we will start checking before above thread starts processing - for i in range(2000): - time.sleep(0.001) - abortres = self.nodes[1].abortrescan() - if abortres: break - assert abortres # if false, we failed to abort - # import should die soon - for i in range(10): - time.sleep(0.1) - deadres = not importthread.isAlive() - if deadres: break - - assert deadres # if false, importthread did not die soon enough - assert_equal(self.nodes[1].getbalance(), 0.0) - - # Import a different address and let it run - self.nodes[1].importprivkey(self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())) - # Expect original privkey to now also be discovered and added to balance - assert_equal(self.nodes[1].getbalance(), Decimal("0.123")) - -if __name__ == "__main__": - ImportAbortRescanTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 6187ddf4013b..2402ccd05006 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -122,7 +122,6 @@ 'rpcnamedargs.py', 'listsinceblock.py', 'p2p-leaktests.py', - 'import-abort-rescan.py', 'p2p-compactblocks.py', 'sporks.py', 'p2p-fingerprint.py', From 8c420c298343dc54ea2ae39f3e7b230bc3bfb390 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 6 May 2017 12:00:01 +0200 Subject: [PATCH 212/987] Merge #10344: [tests] Fix abandonconflict.py intermittency 965a124 [tests] Fix abandonconflict.py intermittency (John Newbery) Tree-SHA512: e0aeeaa2713fb842b92d8c474823b4ed4b7adb840c59141c99216f6611998339776afe0be17a53da9e85137fd53fd8d4985e11a65476765ee1c97df36e237142 --- test/functional/abandonconflict.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/functional/abandonconflict.py b/test/functional/abandonconflict.py index 0439d168dead..974875764168 100755 --- a/test/functional/abandonconflict.py +++ b/test/functional/abandonconflict.py @@ -10,10 +10,8 @@ which are not included in a block and are not currently in the mempool. It has no effect on transactions which are already conflicted or abandoned. """ - from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -import urllib.parse class AbandonConflictTest(BitcoinTestFramework): def __init__(self): @@ -37,8 +35,8 @@ def run_test(self): assert(balance - newbalance < Decimal("0.001")) #no more than fees lost balance = newbalance - url = urllib.parse.urlparse(self.nodes[1].url) - self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1))) + # Disconnect nodes so node0's transactions don't get into node1's mempool + disconnect_nodes(self.nodes[0], 1) # Identify the 10btc outputs nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == Decimal("10")) @@ -78,8 +76,9 @@ def run_test(self): stop_node(self.nodes[0],0) self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) - # Verify txs no longer in mempool + # Verify txs no longer in either node's mempool assert_equal(len(self.nodes[0].getrawmempool()), 0) + assert_equal(len(self.nodes[1].getrawmempool()), 0) # Not in mempool txs from self should only reduce balance # inputs are still spent, but change not received From d6e83980da97ea27279c21156e31d0e2285ff7c7 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sat, 6 May 2017 12:20:50 +0200 Subject: [PATCH 213/987] Merge #10318: [tests] fix wait_for_inv() 3e3c22f [tests] fix wait_for_inv() (John Newbery) Tree-SHA512: b8070b8461e9c792cc3d9c17fd9d3faf87f550c7c0fc1788e0cd382f0794932b70cc87d480805a3b3c1ca2fdca9f8f1bcb9759300d777d9aaa8d41c016260d93 --- test/functional/p2p-segwit.py | 0 test/functional/test_framework/mininode.py | 7 ++++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100755 test/functional/p2p-segwit.py diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index bcc7db8bb759..de93038faad6 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -1737,7 +1737,12 @@ def wait_for_getheaders(self, timeout=60): assert wait_until(test_function, timeout=timeout) def wait_for_inv(self, expected_inv, timeout=60): - test_function = lambda: self.last_message.get("inv") and self.last_message["inv"] != expected_inv + """Waits for an INV message and checks that the first inv object in the message was as expected.""" + if len(expected_inv) > 1: + raise NotImplementedError("wait_for_inv() will only verify the first inv object") + test_function = lambda: self.last_message.get("inv") and \ + self.last_message["inv"].inv[0].type == expected_inv[0].type and \ + self.last_message["inv"].inv[0].hash == expected_inv[0].hash assert wait_until(test_function, timeout=timeout) def wait_for_verack(self, timeout=60): From 2edd094a216c1570d3a3a695d7989e05f2c9fc22 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 7 May 2017 09:59:42 +0200 Subject: [PATCH 214/987] Merge #10189: devtools/net: add a verifier for scriptable changes. Use it to make CNode::id private. 0f3471f net: make CNode's id private (Cory Fields) 9ff0a51 scripted-diff: net: Use accessor rather than node's id directly (Cory Fields) e50c33e devtools: add script to verify scriptable changes (Cory Fields) skipped travis changes Tree-SHA512: a0ff50f4e1d38a2b63109b4996546c91b3e02e00d92c0bf04f48792948f78b1f6d9227a15d25c823fd4723a0277fc6a32c2c1287c7abbb7e50fd82ffb0f8d994 pnode->id to pnode->GetId() Signed-off-by: Pasta --- contrib/devtools/commit-script-check.sh | 39 ++++++++ src/evo/mnauth.cpp | 16 ++-- src/governance/governance.cpp | 28 +++--- src/instantsend.cpp | 4 +- src/llmq/quorums_blockprocessor.cpp | 22 ++--- src/llmq/quorums_chainlocks.cpp | 2 +- src/llmq/quorums_dkgsessionhandler.cpp | 8 +- src/llmq/quorums_dkgsessionmgr.cpp | 4 +- src/llmq/quorums_instantsend.cpp | 10 +- src/llmq/quorums_signing.cpp | 8 +- src/llmq/quorums_signing_shares.cpp | 76 +++++++-------- src/masternode/masternode-sync.cpp | 6 +- src/masternode/masternode-utils.cpp | 2 +- src/net.cpp | 18 ++-- src/net.h | 2 +- src/net_processing.cpp | 122 ++++++++++++------------ src/privatesend/privatesend-client.cpp | 10 +- src/privatesend/privatesend-server.cpp | 10 +- src/spork.cpp | 2 +- 19 files changed, 214 insertions(+), 175 deletions(-) create mode 100755 contrib/devtools/commit-script-check.sh diff --git a/contrib/devtools/commit-script-check.sh b/contrib/devtools/commit-script-check.sh new file mode 100755 index 000000000000..add4bb4883d4 --- /dev/null +++ b/contrib/devtools/commit-script-check.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# Copyright (c) 2017 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# This simple script checks for commits beginning with: scripted-diff: +# If found, looks for a script between the lines -BEGIN VERIFY SCRIPT- and +# -END VERIFY SCRIPT-. If no ending is found, it reads until the end of the +# commit message. + +# The resulting script should exactly transform the previous commit into the current +# one. Any remaining diff signals an error. + +if test "x$1" = "x"; then + echo "Usage: $0 ..." + exit 1 +fi + +RET=0 +PREV_BRANCH=`git name-rev --name-only HEAD` +PREV_HEAD=`git rev-parse HEAD` +for i in `git rev-list --reverse $1`; do + git rev-list -n 1 --pretty="%s" $i | grep -q "^scripted-diff:" || continue + git checkout --quiet $i^ || exit + SCRIPT="`git rev-list --format=%b -n1 $i | sed '/^-BEGIN VERIFY SCRIPT-$/,/^-END VERIFY SCRIPT-$/{//!b};d'`" + if test "x$SCRIPT" = "x"; then + echo "Error: missing script for: $i" + echo "Failed" + RET=1 + else + echo "Running script for: $i" + echo "$SCRIPT" + eval "$SCRIPT" + git --no-pager diff --exit-code $i && echo "OK" || (echo "Failed"; false) || RET=1 + fi + git reset --quiet --hard HEAD +done +git checkout --quiet $PREV_BRANCH 2>/dev/null || git checkout --quiet $PREV_HEAD +exit $RET diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index ca735514fdfd..f8a6de9ec7f5 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -39,7 +39,7 @@ void CMNAuth::PushMNAUTH(CNode* pnode, CConnman& connman) mnauth.proRegTxHash = activeMasternodeInfo.proTxHash; mnauth.sig = activeMasternodeInfo.blsKeyOperator->Sign(signHash); - LogPrint(BCLog::NET, "CMNAuth::%s -- Sending MNAUTH, peer=%d\n", __func__, pnode->id); + LogPrint(BCLog::NET, "CMNAuth::%s -- Sending MNAUTH, peer=%d\n", __func__, pnode->GetId()); connman.PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::MNAUTH, mnauth)); } @@ -60,14 +60,14 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS // only one MNAUTH allowed if (!pnode->verifiedProRegTxHash.IsNull()) { LOCK(cs_main); - Misbehaving(pnode->id, 100); + Misbehaving(pnode->GetId(), 100); return; } } if (mnauth.proRegTxHash.IsNull() || !mnauth.sig.IsValid()) { LOCK(cs_main); - Misbehaving(pnode->id, 100); + Misbehaving(pnode->GetId(), 100); return; } @@ -78,7 +78,7 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS // in case he was unlucky and not up to date, just let him be connected as a regular node, which gives him // a chance to get up-to-date and thus realize by himself that he's not a MN anymore. We still give him a // low DoS score. - Misbehaving(pnode->id, 10); + Misbehaving(pnode->GetId(), 10); return; } @@ -93,14 +93,14 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS LOCK(cs_main); // Same as above, MN seems to not know about his fate yet, so give him a chance to update. If this is a // malicious actor (DoSing us), we'll ban him soon. - Misbehaving(pnode->id, 10); + Misbehaving(pnode->GetId(), 10); return; } connman.ForEachNode([&](CNode* pnode2) { if (pnode2->verifiedProRegTxHash == mnauth.proRegTxHash) { LogPrint(BCLog::NET, "CMNAuth::ProcessMessage -- Masternode %s has already verified as peer %d, dropping old connection. peer=%d\n", - mnauth.proRegTxHash.ToString(), pnode2->id, pnode->id); + mnauth.proRegTxHash.ToString(), pnode2->GetId(), pnode->GetId()); pnode2->fDisconnect = true; } }); @@ -111,7 +111,7 @@ void CMNAuth::ProcessMessage(CNode* pnode, const std::string& strCommand, CDataS pnode->verifiedPubKeyHash = dmn->pdmnState->pubKeyOperator.GetHash(); } - LogPrint(BCLog::NET, "CMNAuth::%s -- Valid MNAUTH for %s, peer=%d\n", __func__, mnauth.proRegTxHash.ToString(), pnode->id); + LogPrint(BCLog::NET, "CMNAuth::%s -- Valid MNAUTH for %s, peer=%d\n", __func__, mnauth.proRegTxHash.ToString(), pnode->GetId()); } } @@ -141,7 +141,7 @@ void CMNAuth::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& if (doRemove) { LogPrint(BCLog::NET, "CMNAuth::NotifyMasternodeListChanged -- Disconnecting MN %s due to key changed/removed, peer=%d\n", - pnode->verifiedProRegTxHash.ToString(), pnode->id); + pnode->verifiedProRegTxHash.ToString(), pnode->GetId()); pnode->fDisconnect = true; } }); diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index a7c600f64a93..18155ca7abbb 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -94,7 +94,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm // ANOTHER USER IS ASKING US TO HELP THEM SYNC GOVERNANCE OBJECT DATA if (strCommand == NetMsgType::MNGOVERNANCESYNC) { if (pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) { - LogPrint(BCLog::GOBJECT, "MNGOVERNANCESYNC -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCESYNC -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_GOVERNANCE_PEER_PROTO_VERSION))); return; } @@ -139,7 +139,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm } if (pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) { - LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECT -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_GOVERNANCE_PEER_PROTO_VERSION))); return; } @@ -214,7 +214,7 @@ void CGovernanceManager::ProcessMessage(CNode* pfrom, const std::string& strComm } if (pfrom->nVersion < MIN_GOVERNANCE_PEER_PROTO_VERSION) { - LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::GOBJECT, "MNGOVERNANCEOBJECTVOTE -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_GOVERNANCE_PEER_PROTO_VERSION))); } @@ -613,24 +613,24 @@ void CGovernanceManager::SyncSingleObjVotes(CNode* pnode, const uint256& nProp, // SYNC GOVERNANCE OBJECTS WITH OTHER CLIENT - LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing single object to peer=%d, nProp = %s\n", __func__, pnode->id, nProp.ToString()); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing single object to peer=%d, nProp = %s\n", __func__, pnode->GetId(), nProp.ToString()); LOCK2(cs_main, cs); // single valid object and its valid votes object_m_it it = mapObjects.find(nProp); if (it == mapObjects.end()) { - LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- no matching object for hash %s, peer=%d\n", __func__, nProp.ToString(), pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- no matching object for hash %s, peer=%d\n", __func__, nProp.ToString(), pnode->GetId()); return; } CGovernanceObject& govobj = it->second; std::string strHash = it->first.ToString(); - LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- attempting to sync govobj: %s, peer=%d\n", __func__, strHash, pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- attempting to sync govobj: %s, peer=%d\n", __func__, strHash, pnode->GetId()); if (govobj.IsSetCachedDelete() || govobj.IsSetExpired()) { LogPrintf("CGovernanceManager::%s -- not syncing deleted/expired govobj: %s, peer=%d\n", __func__, - strHash, pnode->id); + strHash, pnode->GetId()); return; } @@ -650,7 +650,7 @@ void CGovernanceManager::SyncSingleObjVotes(CNode* pnode, const uint256& nProp, CNetMsgMaker msgMaker(pnode->GetSendVersion()); connman.PushMessage(pnode, msgMaker.Make(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_GOVOBJ_VOTE, nVoteCount)); - LogPrintf("CGovernanceManager::%s -- sent %d votes to peer=%d\n", __func__, nVoteCount, pnode->id); + LogPrintf("CGovernanceManager::%s -- sent %d votes to peer=%d\n", __func__, nVoteCount, pnode->GetId()); } void CGovernanceManager::SyncObjects(CNode* pnode, CConnman& connman) const @@ -671,7 +671,7 @@ void CGovernanceManager::SyncObjects(CNode* pnode, CConnman& connman) const // SYNC GOVERNANCE OBJECTS WITH OTHER CLIENT - LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing all objects to peer=%d\n", __func__, pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing all objects to peer=%d\n", __func__, pnode->GetId()); LOCK2(cs_main, cs); @@ -681,23 +681,23 @@ void CGovernanceManager::SyncObjects(CNode* pnode, CConnman& connman) const const CGovernanceObject& govobj = objPair.second; std::string strHash = nHash.ToString(); - LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- attempting to sync govobj: %s, peer=%d\n", __func__, strHash, pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- attempting to sync govobj: %s, peer=%d\n", __func__, strHash, pnode->GetId()); if (govobj.IsSetCachedDelete() || govobj.IsSetExpired()) { LogPrintf("CGovernanceManager::%s -- not syncing deleted/expired govobj: %s, peer=%d\n", __func__, - strHash, pnode->id); + strHash, pnode->GetId()); continue; } // Push the inventory budget proposal message over to the other client - LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing govobj: %s, peer=%d\n", __func__, strHash, pnode->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::%s -- syncing govobj: %s, peer=%d\n", __func__, strHash, pnode->GetId()); pnode->PushInventory(CInv(MSG_GOVERNANCE_OBJECT, nHash)); ++nObjCount; } CNetMsgMaker msgMaker(pnode->GetSendVersion()); connman.PushMessage(pnode, msgMaker.Make(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_GOVOBJ, nObjCount)); - LogPrintf("CGovernanceManager::%s -- sent %d objects to peer=%d\n", __func__, nObjCount, pnode->id); + LogPrintf("CGovernanceManager::%s -- sent %d objects to peer=%d\n", __func__, nObjCount, pnode->GetId()); } void CGovernanceManager::MasternodeRateUpdate(const CGovernanceObject& govobj) @@ -944,7 +944,7 @@ void CGovernanceManager::RequestGovernanceObject(CNode* pfrom, const uint256& nH } } - LogPrint(BCLog::GOBJECT, "CGovernanceManager::RequestGovernanceObject -- nHash %s nVoteCount %d peer=%d\n", nHash.ToString(), nVoteCount, pfrom->id); + LogPrint(BCLog::GOBJECT, "CGovernanceManager::RequestGovernanceObject -- nHash %s nVoteCount %d peer=%d\n", nHash.ToString(), nVoteCount, pfrom->GetId()); connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNGOVERNANCESYNC, nHash, filter)); } diff --git a/src/instantsend.cpp b/src/instantsend.cpp index 21d2729963e6..d8129659b4af 100644 --- a/src/instantsend.cpp +++ b/src/instantsend.cpp @@ -63,7 +63,7 @@ void CInstantSend::ProcessMessage(CNode* pfrom, const std::string& strCommand, C if (strCommand == NetMsgType::TXLOCKVOTE) { // InstantSend Transaction Lock Consensus Votes if(pfrom->nVersion < MIN_INSTANTSEND_PROTO_VERSION) { - LogPrint(BCLog::INSTANTSEND, "TXLOCKVOTE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::INSTANTSEND, "TXLOCKVOTE -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_INSTANTSEND_PROTO_VERSION))); return; @@ -364,7 +364,7 @@ bool CInstantSend::ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, C if (itMnOV->second > GetTime() && itMnOV->second > GetAverageMasternodeOrphanVoteTime()) { LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- masternode is spamming orphan Transaction Lock Votes: txid=%s masternode=%s\n", __func__, txHash.ToString(), vote.GetMasternodeOutpoint().ToStringShort()); - // Misbehaving(pfrom->id, 1); + // Misbehaving(pfrom->GetId(), 1); return false; } // not spamming, refresh diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index d44616cbd8bc..a32c900eb163 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -41,16 +41,16 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC if (qc.IsNull()) { LOCK(cs_main); - LogPrintf("CQuorumBlockProcessor::%s -- null commitment from peer=%d\n", __func__, pfrom->id); - Misbehaving(pfrom->id, 100); + LogPrintf("CQuorumBlockProcessor::%s -- null commitment from peer=%d\n", __func__, pfrom->GetId()); + Misbehaving(pfrom->GetId(), 100); return; } if (!Params().GetConsensus().llmqs.count((Consensus::LLMQType)qc.llmqType)) { LOCK(cs_main); LogPrintf("llmq""CQuorumBlockProcessor::%s -- invalid commitment type %d from peer=%d\n", __func__, - qc.llmqType, pfrom->id); - Misbehaving(pfrom->id, 100); + qc.llmqType, pfrom->GetId()); + Misbehaving(pfrom->GetId(), 100); return; } auto type = (Consensus::LLMQType)qc.llmqType; @@ -61,7 +61,7 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC LOCK(cs_main); if (!mapBlockIndex.count(qc.quorumHash)) { LogPrintf("CQuorumBlockProcessor::%s -- unknown block %s in commitment, peer=%d\n", __func__, - qc.quorumHash.ToString(), pfrom->id); + qc.quorumHash.ToString(), pfrom->GetId()); // can't really punish the node here, as we might simply be the one that is on the wrong chain or not // fully synced return; @@ -69,15 +69,15 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC auto pquorumIndex = mapBlockIndex[qc.quorumHash]; if (chainActive.Tip()->GetAncestor(pquorumIndex->nHeight) != pquorumIndex) { LogPrintf("CQuorumBlockProcessor::%s -- block %s not in active chain, peer=%d\n", __func__, - qc.quorumHash.ToString(), pfrom->id); + qc.quorumHash.ToString(), pfrom->GetId()); // same, can't punish return; } int quorumHeight = pquorumIndex->nHeight - (pquorumIndex->nHeight % params.dkgInterval); if (quorumHeight != pquorumIndex->nHeight) { LogPrintf("CQuorumBlockProcessor::%s -- block %s is not the first block in the DKG interval, peer=%d\n", __func__, - qc.quorumHash.ToString(), pfrom->id); - Misbehaving(pfrom->id, 100); + qc.quorumHash.ToString(), pfrom->GetId()); + Misbehaving(pfrom->GetId(), 100); return; } } @@ -103,13 +103,13 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC if (!qc.Verify(members, true)) { LOCK(cs_main); LogPrintf("CQuorumBlockProcessor::%s -- commitment for quorum %s:%d is not valid, peer=%d\n", __func__, - qc.quorumHash.ToString(), qc.llmqType, pfrom->id); - Misbehaving(pfrom->id, 100); + qc.quorumHash.ToString(), qc.llmqType, pfrom->GetId()); + Misbehaving(pfrom->GetId(), 100); return; } LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- received commitment for quorum %s:%d, validMembers=%d, signers=%d, peer=%d\n", __func__, - qc.quorumHash.ToString(), qc.llmqType, qc.CountValidMembers(), qc.CountSigners(), pfrom->id); + qc.quorumHash.ToString(), qc.llmqType, qc.CountValidMembers(), qc.CountSigners(), pfrom->GetId()); AddMinableCommitment(qc); } diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 78ad22e8f524..5a8a37b9a1e1 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -84,7 +84,7 @@ void CChainLocksHandler::ProcessMessage(CNode* pfrom, const std::string& strComm auto hash = ::SerializeHash(clsig); - ProcessNewChainLock(pfrom->id, clsig, hash); + ProcessNewChainLock(pfrom->GetId(), clsig, hash); } } diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index 629b8bf3c846..c1b4bafe92ed 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -129,13 +129,13 @@ void CDKGSessionHandler::ProcessMessage(CNode* pfrom, const std::string& strComm { // We don't handle messages in the calling thread as deserialization/processing of these would block everything if (strCommand == NetMsgType::QCONTRIB) { - pendingContributions.PushPendingMessage(pfrom->id, vRecv); + pendingContributions.PushPendingMessage(pfrom->GetId(), vRecv); } else if (strCommand == NetMsgType::QCOMPLAINT) { - pendingComplaints.PushPendingMessage(pfrom->id, vRecv); + pendingComplaints.PushPendingMessage(pfrom->GetId(), vRecv); } else if (strCommand == NetMsgType::QJUSTIFICATION) { - pendingJustifications.PushPendingMessage(pfrom->id, vRecv); + pendingJustifications.PushPendingMessage(pfrom->GetId(), vRecv); } else if (strCommand == NetMsgType::QPCOMMITMENT) { - pendingPrematureCommitments.PushPendingMessage(pfrom->id, vRecv); + pendingPrematureCommitments.PushPendingMessage(pfrom->GetId(), vRecv); } } diff --git a/src/llmq/quorums_dkgsessionmgr.cpp b/src/llmq/quorums_dkgsessionmgr.cpp index 1f081a4a1ea6..2370e931085c 100644 --- a/src/llmq/quorums_dkgsessionmgr.cpp +++ b/src/llmq/quorums_dkgsessionmgr.cpp @@ -86,7 +86,7 @@ void CDKGSessionManager::ProcessMessage(CNode* pfrom, const std::string& strComm if (vRecv.size() < 1) { LOCK(cs_main); - Misbehaving(pfrom->id, 100); + Misbehaving(pfrom->GetId(), 100); return; } @@ -94,7 +94,7 @@ void CDKGSessionManager::ProcessMessage(CNode* pfrom, const std::string& strComm Consensus::LLMQType llmqType = (Consensus::LLMQType)*vRecv.begin(); if (!dkgSessionHandlers.count(llmqType)) { LOCK(cs_main); - Misbehaving(pfrom->id, 100); + Misbehaving(pfrom->GetId(), 100); return; } diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 783ddb143642..3b20bcd0fd6e 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -688,10 +688,10 @@ void CInstantSendManager::ProcessMessage(CNode* pfrom, const std::string& strCom void CInstantSendManager::ProcessMessageInstantSendLock(CNode* pfrom, const llmq::CInstantSendLock& islock, CConnman& connman) { bool ban = false; - if (!PreVerifyInstantSendLock(pfrom->id, islock, ban)) { + if (!PreVerifyInstantSendLock(pfrom->GetId(), islock, ban)) { if (ban) { LOCK(cs_main); - Misbehaving(pfrom->id, 100); + Misbehaving(pfrom->GetId(), 100); } return; } @@ -707,9 +707,9 @@ void CInstantSendManager::ProcessMessageInstantSendLock(CNode* pfrom, const llmq } LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s, islock=%s: received islock, peer=%d\n", __func__, - islock.txid.ToString(), hash.ToString(), pfrom->id); + islock.txid.ToString(), hash.ToString(), pfrom->GetId()); - pendingInstantSendLocks.emplace(hash, std::make_pair(pfrom->id, std::move(islock))); + pendingInstantSendLocks.emplace(hash, std::make_pair(pfrom->GetId(), std::move(islock))); } bool CInstantSendManager::PreVerifyInstantSendLock(NodeId nodeId, const llmq::CInstantSendLock& islock, bool& retBan) @@ -1300,7 +1300,7 @@ void CInstantSendManager::AskNodesForLockedTx(const uint256& txid) LOCK(cs_main); for (CNode* pnode : nodesToAskFor) { LogPrintf("CInstantSendManager::%s -- txid=%s: asking other peer %d for correct TX\n", __func__, - txid.ToString(), pnode->id); + txid.ToString(), pnode->GetId()); CInv inv(MSG_TX, txid); pnode->AskFor(inv); diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index 58b0c096fc6f..a070ff84d6c0 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -430,10 +430,10 @@ void CSigningManager::ProcessMessage(CNode* pfrom, const std::string& strCommand void CSigningManager::ProcessMessageRecoveredSig(CNode* pfrom, const CRecoveredSig& recoveredSig, CConnman& connman) { bool ban = false; - if (!PreVerifyRecoveredSig(pfrom->id, recoveredSig, ban)) { + if (!PreVerifyRecoveredSig(pfrom->GetId(), recoveredSig, ban)) { if (ban) { LOCK(cs_main); - Misbehaving(pfrom->id, 100); + Misbehaving(pfrom->GetId(), 100); } return; } @@ -444,10 +444,10 @@ void CSigningManager::ProcessMessageRecoveredSig(CNode* pfrom, const CRecoveredS return; } - LogPrint(BCLog::LLMQ, "CSigningManager::%s -- signHash=%s, node=%d\n", __func__, CLLMQUtils::BuildSignHash(recoveredSig).ToString(), pfrom->id); + LogPrint(BCLog::LLMQ, "CSigningManager::%s -- signHash=%s, node=%d\n", __func__, CLLMQUtils::BuildSignHash(recoveredSig).ToString(), pfrom->GetId()); LOCK(cs); - pendingRecoveredSigs[pfrom->id].emplace_back(recoveredSig); + pendingRecoveredSigs[pfrom->GetId()].emplace_back(recoveredSig); } bool CSigningManager::PreVerifyRecoveredSig(NodeId nodeId, const CRecoveredSig& recoveredSig, bool& retBan) diff --git a/src/llmq/quorums_signing_shares.cpp b/src/llmq/quorums_signing_shares.cpp index 2c047498acb5..3d04007e22c7 100644 --- a/src/llmq/quorums_signing_shares.cpp +++ b/src/llmq/quorums_signing_shares.cpp @@ -234,13 +234,13 @@ void CSigSharesManager::ProcessMessage(CNode* pfrom, const std::string& strComma std::vector msgs; vRecv >> msgs; if (msgs.size() > MAX_MSGS_CNT_QSIGSESANN) { - LogPrintf("CSigSharesManager::%s -- too many announcements in QSIGSESANN message. cnt=%d, max=%d, node=%d\n", __func__, msgs.size(), MAX_MSGS_CNT_QSIGSESANN, pfrom->id); - BanNode(pfrom->id); + LogPrintf("CSigSharesManager::%s -- too many announcements in QSIGSESANN message. cnt=%d, max=%d, node=%d\n", __func__, msgs.size(), MAX_MSGS_CNT_QSIGSESANN, pfrom->GetId()); + BanNode(pfrom->GetId()); return; } for (auto& ann : msgs) { if (!ProcessMessageSigSesAnn(pfrom, ann, connman)) { - BanNode(pfrom->id); + BanNode(pfrom->GetId()); return; } } @@ -248,13 +248,13 @@ void CSigSharesManager::ProcessMessage(CNode* pfrom, const std::string& strComma std::vector msgs; vRecv >> msgs; if (msgs.size() > MAX_MSGS_CNT_QSIGSHARESINV) { - LogPrintf("CSigSharesManager::%s -- too many invs in QSIGSHARESINV message. cnt=%d, max=%d, node=%d\n", __func__, msgs.size(), MAX_MSGS_CNT_QSIGSHARESINV, pfrom->id); - BanNode(pfrom->id); + LogPrintf("CSigSharesManager::%s -- too many invs in QSIGSHARESINV message. cnt=%d, max=%d, node=%d\n", __func__, msgs.size(), MAX_MSGS_CNT_QSIGSHARESINV, pfrom->GetId()); + BanNode(pfrom->GetId()); return; } for (auto& inv : msgs) { if (!ProcessMessageSigSharesInv(pfrom, inv, connman)) { - BanNode(pfrom->id); + BanNode(pfrom->GetId()); return; } } @@ -262,13 +262,13 @@ void CSigSharesManager::ProcessMessage(CNode* pfrom, const std::string& strComma std::vector msgs; vRecv >> msgs; if (msgs.size() > MAX_MSGS_CNT_QGETSIGSHARES) { - LogPrintf("CSigSharesManager::%s -- too many invs in QGETSIGSHARES message. cnt=%d, max=%d, node=%d\n", __func__, msgs.size(), MAX_MSGS_CNT_QGETSIGSHARES, pfrom->id); - BanNode(pfrom->id); + LogPrintf("CSigSharesManager::%s -- too many invs in QGETSIGSHARES message. cnt=%d, max=%d, node=%d\n", __func__, msgs.size(), MAX_MSGS_CNT_QGETSIGSHARES, pfrom->GetId()); + BanNode(pfrom->GetId()); return; } for (auto& inv : msgs) { if (!ProcessMessageGetSigShares(pfrom, inv, connman)) { - BanNode(pfrom->id); + BanNode(pfrom->GetId()); return; } } @@ -280,13 +280,13 @@ void CSigSharesManager::ProcessMessage(CNode* pfrom, const std::string& strComma totalSigsCount += bs.sigShares.size(); } if (totalSigsCount > MAX_MSGS_TOTAL_BATCHED_SIGS) { - LogPrintf("CSigSharesManager::%s -- too many sigs in QBSIGSHARES message. cnt=%d, max=%d, node=%d\n", __func__, msgs.size(), MAX_MSGS_TOTAL_BATCHED_SIGS, pfrom->id); - BanNode(pfrom->id); + LogPrintf("CSigSharesManager::%s -- too many sigs in QBSIGSHARES message. cnt=%d, max=%d, node=%d\n", __func__, msgs.size(), MAX_MSGS_TOTAL_BATCHED_SIGS, pfrom->GetId()); + BanNode(pfrom->GetId()); return; } for (auto& bs : msgs) { if (!ProcessMessageBatchedSigShares(pfrom, bs, connman)) { - BanNode(pfrom->id); + BanNode(pfrom->GetId()); return; } } @@ -303,20 +303,20 @@ bool CSigSharesManager::ProcessMessageSigSesAnn(CNode* pfrom, const CSigSesAnn& return false; } - LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- ann={%s}, node=%d\n", __func__, ann.ToString(), pfrom->id); + LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- ann={%s}, node=%d\n", __func__, ann.ToString(), pfrom->GetId()); auto quorum = quorumManager->GetQuorum(llmqType, ann.quorumHash); if (!quorum) { // TODO should we ban here? LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- quorum %s not found, node=%d\n", __func__, - ann.quorumHash.ToString(), pfrom->id); + ann.quorumHash.ToString(), pfrom->GetId()); return true; // let's still try other announcements from the same message } auto signHash = CLLMQUtils::BuildSignHash(llmqType, ann.quorumHash, ann.id, ann.msgHash); LOCK(cs); - auto& nodeState = nodeStates[pfrom->id]; + auto& nodeState = nodeStates[pfrom->GetId()]; auto& session = nodeState.GetOrCreateSessionFromAnn(ann); nodeState.sessionByRecvId.erase(session.recvSessionId); nodeState.sessionByRecvId.erase(ann.sessionId); @@ -340,11 +340,11 @@ bool CSigSharesManager::VerifySigSharesInv(NodeId from, Consensus::LLMQType llmq bool CSigSharesManager::ProcessMessageSigSharesInv(CNode* pfrom, const CSigSharesInv& inv, CConnman& connman) { CSigSharesNodeState::SessionInfo sessionInfo; - if (!GetSessionInfoByRecvId(pfrom->id, inv.sessionId, sessionInfo)) { + if (!GetSessionInfoByRecvId(pfrom->GetId(), inv.sessionId, sessionInfo)) { return true; } - if (!VerifySigSharesInv(pfrom->id, sessionInfo.llmqType, inv)) { + if (!VerifySigSharesInv(pfrom->GetId(), sessionInfo.llmqType, inv)) { return false; } @@ -354,17 +354,17 @@ bool CSigSharesManager::ProcessMessageSigSharesInv(CNode* pfrom, const CSigShare } LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signHash=%s, inv={%s}, node=%d\n", __func__, - sessionInfo.signHash.ToString(), inv.ToString(), pfrom->id); + sessionInfo.signHash.ToString(), inv.ToString(), pfrom->GetId()); if (sessionInfo.quorum->quorumVvec == nullptr) { // TODO we should allow to ask other nodes for the quorum vvec if we missed it in the DKG LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- we don't have the quorum vvec for %s, not requesting sig shares. node=%d\n", __func__, - sessionInfo.quorumHash.ToString(), pfrom->id); + sessionInfo.quorumHash.ToString(), pfrom->GetId()); return true; } LOCK(cs); - auto& nodeState = nodeStates[pfrom->id]; + auto& nodeState = nodeStates[pfrom->GetId()]; auto session = nodeState.GetSessionByRecvId(inv.sessionId); if (!session) { return true; @@ -377,11 +377,11 @@ bool CSigSharesManager::ProcessMessageSigSharesInv(CNode* pfrom, const CSigShare bool CSigSharesManager::ProcessMessageGetSigShares(CNode* pfrom, const CSigSharesInv& inv, CConnman& connman) { CSigSharesNodeState::SessionInfo sessionInfo; - if (!GetSessionInfoByRecvId(pfrom->id, inv.sessionId, sessionInfo)) { + if (!GetSessionInfoByRecvId(pfrom->GetId(), inv.sessionId, sessionInfo)) { return true; } - if (!VerifySigSharesInv(pfrom->id, sessionInfo.llmqType, inv)) { + if (!VerifySigSharesInv(pfrom->GetId(), sessionInfo.llmqType, inv)) { return false; } @@ -391,10 +391,10 @@ bool CSigSharesManager::ProcessMessageGetSigShares(CNode* pfrom, const CSigShare } LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signHash=%s, inv={%s}, node=%d\n", __func__, - sessionInfo.signHash.ToString(), inv.ToString(), pfrom->id); + sessionInfo.signHash.ToString(), inv.ToString(), pfrom->GetId()); LOCK(cs); - auto& nodeState = nodeStates[pfrom->id]; + auto& nodeState = nodeStates[pfrom->GetId()]; auto session = nodeState.GetSessionByRecvId(inv.sessionId); if (!session) { return true; @@ -407,12 +407,12 @@ bool CSigSharesManager::ProcessMessageGetSigShares(CNode* pfrom, const CSigShare bool CSigSharesManager::ProcessMessageBatchedSigShares(CNode* pfrom, const CBatchedSigShares& batchedSigShares, CConnman& connman) { CSigSharesNodeState::SessionInfo sessionInfo; - if (!GetSessionInfoByRecvId(pfrom->id, batchedSigShares.sessionId, sessionInfo)) { + if (!GetSessionInfoByRecvId(pfrom->GetId(), batchedSigShares.sessionId, sessionInfo)) { return true; } bool ban = false; - if (!PreVerifyBatchedSigShares(pfrom->id, sessionInfo, batchedSigShares, ban)) { + if (!PreVerifyBatchedSigShares(pfrom->GetId(), sessionInfo, batchedSigShares, ban)) { return !ban; } @@ -421,7 +421,7 @@ bool CSigSharesManager::ProcessMessageBatchedSigShares(CNode* pfrom, const CBatc { LOCK(cs); - auto& nodeState = nodeStates[pfrom->id]; + auto& nodeState = nodeStates[pfrom->GetId()]; for (size_t i = 0; i < batchedSigShares.sigShares.size(); i++) { CSigShare sigShare = RebuildSigShare(sessionInfo, batchedSigShares, i); @@ -445,14 +445,14 @@ bool CSigSharesManager::ProcessMessageBatchedSigShares(CNode* pfrom, const CBatc } LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- signHash=%s, shares=%d, new=%d, inv={%s}, node=%d\n", __func__, - sessionInfo.signHash.ToString(), batchedSigShares.sigShares.size(), sigShares.size(), batchedSigShares.ToInvString(), pfrom->id); + sessionInfo.signHash.ToString(), batchedSigShares.sigShares.size(), sigShares.size(), batchedSigShares.ToInvString(), pfrom->GetId()); if (sigShares.empty()) { return true; } LOCK(cs); - auto& nodeState = nodeStates[pfrom->id]; + auto& nodeState = nodeStates[pfrom->GetId()]; for (auto& s : sigShares) { nodeState.pendingIncomingSigShares.Add(s.GetKey(), s); } @@ -1038,13 +1038,13 @@ bool CSigSharesManager::SendMessages() for (auto& pnode : vNodesCopy) { CNetMsgMaker msgMaker(pnode->GetSendVersion()); - auto it1 = sigSessionAnnouncements.find(pnode->id); + auto it1 = sigSessionAnnouncements.find(pnode->GetId()); if (it1 != sigSessionAnnouncements.end()) { std::vector msgs; msgs.reserve(it1->second.size()); for (auto& sigSesAnn : it1->second) { LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::SendMessages -- QSIGSESANN signHash=%s, sessionId=%d, node=%d\n", - CLLMQUtils::BuildSignHash(sigSesAnn).ToString(), sigSesAnn.sessionId, pnode->id); + CLLMQUtils::BuildSignHash(sigSesAnn).ToString(), sigSesAnn.sessionId, pnode->GetId()); msgs.emplace_back(sigSesAnn); if (msgs.size() == MAX_MSGS_CNT_QSIGSESANN) { g_connman->PushMessage(pnode, msgMaker.Make(NetMsgType::QSIGSESANN, msgs), false); @@ -1058,13 +1058,13 @@ bool CSigSharesManager::SendMessages() } } - auto it = sigSharesToRequest.find(pnode->id); + auto it = sigSharesToRequest.find(pnode->GetId()); if (it != sigSharesToRequest.end()) { std::vector msgs; for (auto& p : it->second) { assert(p.second.CountSet() != 0); LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::SendMessages -- QGETSIGSHARES signHash=%s, inv={%s}, node=%d\n", - p.first.ToString(), p.second.ToString(), pnode->id); + p.first.ToString(), p.second.ToString(), pnode->GetId()); msgs.emplace_back(std::move(p.second)); if (msgs.size() == MAX_MSGS_CNT_QGETSIGSHARES) { g_connman->PushMessage(pnode, msgMaker.Make(NetMsgType::QGETSIGSHARES, msgs), false); @@ -1078,14 +1078,14 @@ bool CSigSharesManager::SendMessages() } } - auto jt = sigSharesToSend.find(pnode->id); + auto jt = sigSharesToSend.find(pnode->GetId()); if (jt != sigSharesToSend.end()) { size_t totalSigsCount = 0; std::vector msgs; for (auto& p : jt->second) { assert(!p.second.sigShares.empty()); LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::SendMessages -- QBSIGSHARES signHash=%s, inv={%s}, node=%d\n", - p.first.ToString(), p.second.ToInvString(), pnode->id); + p.first.ToString(), p.second.ToInvString(), pnode->GetId()); if (totalSigsCount + p.second.sigShares.size() > MAX_MSGS_TOTAL_BATCHED_SIGS) { g_connman->PushMessage(pnode, msgMaker.Make(NetMsgType::QBSIGSHARES, msgs), false); msgs.clear(); @@ -1102,13 +1102,13 @@ bool CSigSharesManager::SendMessages() } } - auto kt = sigSharesToAnnounce.find(pnode->id); + auto kt = sigSharesToAnnounce.find(pnode->GetId()); if (kt != sigSharesToAnnounce.end()) { std::vector msgs; for (auto& p : kt->second) { assert(p.second.CountSet() != 0); LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::SendMessages -- QSIGSHARESINV signHash=%s, inv={%s}, node=%d\n", - p.first.ToString(), p.second.ToString(), pnode->id); + p.first.ToString(), p.second.ToString(), pnode->GetId()); msgs.emplace_back(std::move(p.second)); if (msgs.size() == MAX_MSGS_CNT_QSIGSHARESINV) { g_connman->PushMessage(pnode, msgMaker.Make(NetMsgType::QSIGSHARESINV, msgs), false); @@ -1261,7 +1261,7 @@ void CSigSharesManager::Cleanup() nodeStatesToDelete.emplace(p.first); } g_connman->ForEachNode([&](CNode* pnode) { - nodeStatesToDelete.erase(pnode->id); + nodeStatesToDelete.erase(pnode->GetId()); }); // Now delete these node states diff --git a/src/masternode/masternode-sync.cpp b/src/masternode/masternode-sync.cpp index 47bf99017696..d66b4ac55eb4 100644 --- a/src/masternode/masternode-sync.cpp +++ b/src/masternode/masternode-sync.cpp @@ -107,7 +107,7 @@ void CMasternodeSync::ProcessMessage(CNode* pfrom, const std::string& strCommand int nCount; vRecv >> nItemID >> nCount; - LogPrintf("SYNCSTATUSCOUNT -- got inventory count: nItemID=%d nCount=%d peer=%d\n", nItemID, nCount, pfrom->id); + LogPrintf("SYNCSTATUSCOUNT -- got inventory count: nItemID=%d nCount=%d peer=%d\n", nItemID, nCount, pfrom->GetId()); } } @@ -188,7 +188,7 @@ void CMasternodeSync::ProcessTick(CConnman& connman) // We already fully synced from this node recently, // disconnect to free this connection slot for another peer. pnode->fDisconnect = true; - LogPrintf("CMasternodeSync::ProcessTick -- disconnecting from recently synced peer=%d\n", pnode->id); + LogPrintf("CMasternodeSync::ProcessTick -- disconnecting from recently synced peer=%d\n", pnode->GetId()); continue; } @@ -199,7 +199,7 @@ void CMasternodeSync::ProcessTick(CConnman& connman) netfulfilledman.AddFulfilledRequest(pnode->addr, "spork-sync"); // get current network sporks connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETSPORKS)); - LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- requesting sporks from peer=%d\n", nTick, nCurrentAsset, pnode->id); + LogPrintf("CMasternodeSync::ProcessTick -- nTick %d nCurrentAsset %d -- requesting sporks from peer=%d\n", nTick, nCurrentAsset, pnode->GetId()); } // INITIAL TIMEOUT diff --git a/src/masternode/masternode-utils.cpp b/src/masternode/masternode-utils.cpp index f199fc78b520..90c8debdf40c 100644 --- a/src/masternode/masternode-utils.cpp +++ b/src/masternode/masternode-utils.cpp @@ -84,7 +84,7 @@ void CMasternodeUtils::ProcessMasternodeConnections(CConnman& connman) } 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()); + LogPrintf("Closing Masternode connection: peer=%d, addr=%s\n", pnode->GetId(), pnode->addr.ToString()); pnode->fDisconnect = true; } }); diff --git a/src/net.cpp b/src/net.cpp index 219967df3441..5d55e46d950b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -997,7 +997,7 @@ bool CConnman::AttemptToEvictConnection() } } - NodeEvictionCandidate candidate = {node->id, node->nTimeConnected, node->nMinPingUsecTime, + NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime, node->nLastBlockTime, node->nLastTXTime, (node->nServices & nRelevantServices) == nRelevantServices, node->fRelayTxes, node->pfilter != NULL, node->nKeyedNetGroup}; @@ -1197,7 +1197,7 @@ void CConnman::ThreadSocketHandler() if (pnode->fDisconnect) { LogPrintf("ThreadSocketHandler -- removing node: peer=%d addr=%s nRefCount=%d fInbound=%d fMasternode=%d\n", - pnode->id, pnode->addr.ToString(), pnode->GetRefCount(), pnode->fInbound, pnode->fMasternode); + pnode->GetId(), pnode->addr.ToString(), pnode->GetRefCount(), pnode->fInbound, pnode->fMasternode); // remove from vNodes vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end()); @@ -1469,7 +1469,7 @@ void CConnman::ThreadSocketHandler() { if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) { - LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->id); + LogPrint(BCLog::NET, "socket no message in first 60 seconds, %d %d from %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId()); pnode->fDisconnect = true; } else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL) @@ -1489,7 +1489,7 @@ void CConnman::ThreadSocketHandler() } else if (!pnode->fSuccessfullyConnected) { - LogPrintf("version handshake timeout from %d\n", pnode->id); + LogPrintf("version handshake timeout from %d\n", pnode->GetId()); pnode->fDisconnect = true; } } @@ -2779,7 +2779,7 @@ std::set CConnman::GetMasternodeQuorumNodes(Consensus::LLMQType llmqType if (!pnode->qwatch && (pnode->verifiedProRegTxHash.IsNull() || !proRegTxHashes.count(pnode->verifiedProRegTxHash))) { continue; } - nodes.emplace(pnode->id); + nodes.emplace(pnode->GetId()); } return nodes; } @@ -2859,7 +2859,7 @@ bool CConnman::DisconnectNode(NodeId id) { LOCK(cs_vNodes); for(CNode* pnode : vNodes) { - if (id == pnode->id) { + if (id == pnode->GetId()) { pnode->fDisconnect = true; return true; } @@ -3069,10 +3069,10 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn fFirstMessageIsMNAUTH(false), addr(addrIn), fInbound(fInboundIn), - id(idIn), nKeyedNetGroup(nKeyedNetGroupIn), addrKnown(5000, 0.001), filterInventoryKnown(50000, 0.000001), + id(idIn), nLocalHostNonce(nLocalHostNonceIn), nLocalServices(nLocalServicesIn), nMyStartingHeight(nMyStartingHeightIn), @@ -3209,7 +3209,7 @@ void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg, bool allowOpti { size_t nMessageSize = msg.data.size(); size_t nTotalSize = nMessageSize + CMessageHeader::HEADER_SIZE; - LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->id); + LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->GetId()); std::vector serializedHeader; serializedHeader.reserve(CMessageHeader::HEADER_SIZE); @@ -3264,7 +3264,7 @@ bool CConnman::ForNode(NodeId id, std::function cond, CNode* found = nullptr; LOCK(cs_vNodes); for (auto&& pnode : vNodes) { - if(pnode->id == id) { + if(pnode->GetId() == id) { found = pnode; break; } diff --git a/src/net.h b/src/net.h index f97b3e67ad7c..b066c2887dfa 100644 --- a/src/net.h +++ b/src/net.h @@ -771,7 +771,6 @@ class CNode CCriticalSection cs_filter; CBloomFilter* pfilter; std::atomic nRefCount; - const NodeId id; const uint64_t nKeyedNetGroup; @@ -854,6 +853,7 @@ class CNode private: CNode(const CNode&); void operator=(const CNode&); + const NodeId id; const uint64_t nLocalHostNonce; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index ad591ac1b9f4..cbc338ad1cb4 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -874,7 +874,7 @@ void PeerLogicValidation::NewPoWValidBlock(const CBlockIndex *pindex, const std: !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->pprev)) { LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", "PeerLogicValidation::NewPoWValidBlock", - hashBlock.ToString(), pnode->id); + hashBlock.ToString(), pnode->GetId()); connman->PushMessage(pnode, msgMaker.Make(NetMsgType::CMPCTBLOCK, *pcmpctblock)); state.pindexBestHeaderSent = pindex; } @@ -1046,7 +1046,7 @@ static void RelayAddress(const CAddress& addr, bool fReachable, CConnman& connma auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) { if (pnode->nVersion >= CADDR_TIME_VERSION) { - uint64_t hashKey = CSipHasher(hasher).Write(pnode->id).Finalize(); + uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize(); for (unsigned int i = 0; i < nRelayNodes; i++) { if (hashKey > best[i].first) { std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1); @@ -1400,7 +1400,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac if (req.indexes[i] >= block.vtx.size()) { LOCK(cs_main); Misbehaving(pfrom->GetId(), 100); - LogPrintf("Peer %d sent us a getblocktxn with out-of-bounds tx indices", pfrom->id); + LogPrintf("Peer %d sent us a getblocktxn with out-of-bounds tx indices", pfrom->GetId()); return; } resp.txn[i] = block.vtx[req.indexes[i]]; @@ -1412,7 +1412,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, const std::atomic& interruptMsgProc) { - LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id); + LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId()); if (IsArgSet("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 0)) == 0) { LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n"); @@ -1452,7 +1452,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // on rules which are incompatible to ours. Better to ban him after some time as it might otherwise keep // asking for the same block (if -addnode/-connect was used on the other side). LOCK(cs_main); - Misbehaving(pfrom->id, 1); + Misbehaving(pfrom->GetId(), 1); } if (LogAcceptCategory(BCLog::NET)) { @@ -1499,7 +1499,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } if (pfrom->nServicesExpected & ~nServices) { - LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->id, nServices, pfrom->nServicesExpected); + LogPrint(BCLog::NET, "peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom->GetId(), nServices, pfrom->nServicesExpected); connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_NONSTANDARD, strprintf("Expected to offer services %08x", pfrom->nServicesExpected))); pfrom->fDisconnect = true; @@ -1509,7 +1509,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (nVersion < MIN_PEER_PROTO_VERSION) { // disconnect from peers older than this proto version - LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->id, nVersion); + LogPrintf("peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion); connman.PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PEER_PROTO_VERSION))); pfrom->fDisconnect = true; @@ -1629,7 +1629,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LogPrintf("receive version message: %s: version %d, blocks=%d, us=%s, peer=%d%s\n", cleanSubVer, pfrom->nVersion, - pfrom->nStartingHeight, addrMe.ToString(), pfrom->id, + pfrom->nStartingHeight, addrMe.ToString(), pfrom->GetId(), remoteAddr); int64_t nTimeOffset = nTime - GetTime(); @@ -1827,7 +1827,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr const CInv &inv = vInv[nInv]; if(!inv.IsKnownType()) { - LogPrint(BCLog::NET, "got inv of unknown type %d: %s peer=%d\n", inv.type, inv.hash.ToString(), pfrom->id); + LogPrint(BCLog::NET, "got inv of unknown type %d: %s peer=%d\n", inv.type, inv.hash.ToString(), pfrom->GetId()); continue; } @@ -1835,7 +1835,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return true; bool fAlreadyHave = AlreadyHave(inv); - LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->id); + LogPrint(BCLog::NET, "got inv: %s %s peer=%d\n", inv.ToString(), fAlreadyHave ? "have" : "new", pfrom->GetId()); if (inv.type == MSG_BLOCK) { UpdateBlockAvailability(pfrom->GetId(), inv.hash); @@ -1844,7 +1844,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr continue; } - CNodeState *state = State(pfrom->id); + CNodeState *state = State(pfrom->GetId()); if (!state) { continue; } @@ -1863,7 +1863,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // we now only provide a getheaders response here. When we receive the headers, we will // then ask for the blocks we need. connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash)); - LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->id); + LogPrint(BCLog::NET, "getheaders (%d) %s to peer=%d\n", pindexBestHeader->nHeight, inv.hash.ToString(), pfrom->GetId()); } } else @@ -1875,7 +1875,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->AddInventoryKnown(inv); if (fBlocksOnly) { LogPrint(BCLog::NET, "transaction (%s) inv sent in violation of protocol peer=%d\n", inv.hash.ToString(), - pfrom->id); + pfrom->GetId()); } else if (!fAlreadyHave) { bool allowWhileInIBD = allowWhileInIBDObjs.count(inv.type); if (allowWhileInIBD || (!fImporting && !fReindex && !IsInitialBlockDownload())) { @@ -1914,10 +1914,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr return error("message getdata size() = %u", vInv.size()); } - LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->id); + LogPrint(BCLog::NET, "received getdata (%u invsz) peer=%d\n", vInv.size(), pfrom->GetId()); if (vInv.size() > 0) { - LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->id); + LogPrint(BCLog::NET, "received getdata for: %s peer=%d\n", vInv[0].ToString(), pfrom->GetId()); } pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); @@ -1957,7 +1957,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (pindex) pindex = chainActive.Next(pindex); int nLimit = 500; - LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->id); + LogPrint(BCLog::NET, "getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), nLimit, pfrom->GetId()); for (; pindex; pindex = chainActive.Next(pindex)) { if (pindex->GetBlockHash() == hashStop) @@ -2007,7 +2007,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr BlockMap::iterator it = mapBlockIndex.find(req.blockhash); if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) { - LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->id); + LogPrintf("Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId()); return true; } @@ -2019,7 +2019,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // might maliciously send lots of getblocktxn requests to trigger // expensive disk reads, because it will require the peer to // actually receive all the data read from disk over the network. - LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->id, MAX_BLOCKTXN_DEPTH); + LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block > %i deep", pfrom->GetId(), MAX_BLOCKTXN_DEPTH); CInv inv; inv.type = MSG_BLOCK; inv.hash = req.blockhash; @@ -2044,7 +2044,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); if (IsInitialBlockDownload() && !pfrom->fWhitelisted) { - LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->id); + LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because node is in initial block download\n", pfrom->GetId()); return true; } @@ -2074,7 +2074,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end std::vector vHeaders; int nLimit = MAX_HEADERS_RESULTS; - LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->id); + LogPrint(BCLog::NET, "getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ? "end" : hashStop.ToString(), pfrom->GetId()); for (; pindex; pindex = chainActive.Next(pindex)) { vHeaders.push_back(pindex->GetBlockHeader()); @@ -2104,7 +2104,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off if (!fRelayTxes && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))) { - LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->id); + LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->GetId()); return true; } @@ -2199,11 +2199,11 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Process custom txes, this changes AlreadyHave to "true" if (nInvType == MSG_DSTX) { LogPrintf("DSTX -- Masternode transaction accepted, txid=%s, peer=%d\n", - tx.GetHash().ToString(), pfrom->id); + tx.GetHash().ToString(), pfrom->GetId()); CPrivateSend::AddDSTX(dstx); } else if (nInvType == MSG_TXLOCK_REQUEST || fCanAutoLock) { LogPrintf("TXLOCKREQUEST -- Transaction Lock Request accepted, txid=%s, peer=%d\n", - tx.GetHash().ToString(), pfrom->id); + tx.GetHash().ToString(), pfrom->GetId()); instantsend.AcceptLockRequest(txLockRequest); instantsend.Vote(tx.GetHash(), connman); } @@ -2217,7 +2217,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->nLastTXTime = GetTime(); LogPrint(BCLog::MEMPOOL, "AcceptToMemoryPool: peer=%d: accepted %s (poolsz %u txn, %u kB)\n", - pfrom->id, + pfrom->GetId(), tx.GetHash().ToString(), mempool.size(), mempool.DynamicMemoryUsage() / 1000); @@ -2341,10 +2341,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // case. int nDoS = 0; if (!state.IsInvalid(nDoS) || nDoS == 0) { - LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->id); + LogPrintf("Force relaying tx %s from whitelisted peer=%d\n", tx.GetHash().ToString(), pfrom->GetId()); connman.RelayTransaction(tx); } else { - LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->id, FormatStateMessage(state)); + LogPrintf("Not relaying invalid transaction %s from whitelisted peer=%d (%s)\n", tx.GetHash().ToString(), pfrom->GetId(), FormatStateMessage(state)); } } } @@ -2353,7 +2353,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (state.IsInvalid(nDoS)) { LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(), - pfrom->id, + pfrom->GetId(), FormatStateMessage(state)); if (state.GetRejectCode() > 0 && state.GetRejectCode() < REJECT_INTERNAL) // Never send AcceptToMemoryPool's internal codes over P2P connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::REJECT, strCommand, (unsigned char)state.GetRejectCode(), @@ -2389,7 +2389,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); Misbehaving(pfrom->GetId(), nDoS); } - LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->id); + LogPrintf("Peer %d sent us invalid header via cmpctblock\n", pfrom->GetId()); return true; } } @@ -2462,7 +2462,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (status == READ_STATUS_INVALID) { MarkBlockAsReceived(pindex->GetBlockHash()); // Reset in-flight state in case of whitelist Misbehaving(pfrom->GetId(), 100); - LogPrintf("Peer %d sent us invalid compact block\n", pfrom->id); + LogPrintf("Peer %d sent us invalid compact block\n", pfrom->GetId()); return true; } else if (status == READ_STATUS_FAILED) { // Duplicate txindexes, the block is now in-flight, so just request it @@ -2567,7 +2567,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr std::map::iterator> >::iterator it = mapBlocksInFlight.find(resp.blockhash); if (it == mapBlocksInFlight.end() || !it->second.second->partialBlock || it->second.first != pfrom->GetId()) { - LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->id); + LogPrint(BCLog::NET, "Peer %d sent us block transactions for block we weren't expecting\n", pfrom->GetId()); return true; } @@ -2576,7 +2576,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (status == READ_STATUS_INVALID) { MarkBlockAsReceived(resp.blockhash); // Reset in-flight state in case of whitelist Misbehaving(pfrom->GetId(), 100); - LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->id); + LogPrintf("Peer %d sent us invalid compact block/non-matching block transactions\n", pfrom->GetId()); return true; } else if (status == READ_STATUS_FAILED) { // Might have collided, fall back to getdata now :( @@ -2664,7 +2664,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr headers[0].GetHash().ToString(), headers[0].hashPrevBlock.ToString(), pindexBestHeader->nHeight, - pfrom->id, nodestate->nUnconnectingHeaders); + pfrom->GetId(), nodestate->nUnconnectingHeaders); // Set hashLastUnknownBlock for this peer, so that if we // eventually get the headers - even from a different peer - // we can use this peer to download. @@ -2702,7 +2702,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); CNodeState *nodestate = State(pfrom->GetId()); if (nodestate->nUnconnectingHeaders > 0) { - LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->id, nodestate->nUnconnectingHeaders); + LogPrint(BCLog::NET, "peer=%d: resetting nUnconnectingHeaders (%d -> 0)\n", pfrom->GetId(), nodestate->nUnconnectingHeaders); } nodestate->nUnconnectingHeaders = 0; @@ -2713,7 +2713,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Headers message had its maximum size; the peer may have more headers. // TODO: optimize: if pindexLast is an ancestor of chainActive.Tip or pindexBestHeader, continue // from there instead. - LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->id, pfrom->nStartingHeight); + LogPrint(BCLog::NET, "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->nHeight, pfrom->GetId(), pfrom->nStartingHeight); connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256())); } @@ -2751,7 +2751,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex); LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n", - pindex->GetBlockHash().ToString(), pfrom->id); + pindex->GetBlockHash().ToString(), pfrom->GetId()); } if (vGetData.size() > 1) { LogPrint(BCLog::NET, "Downloading blocks toward %s (%d) via headers direct fetch\n", @@ -2774,7 +2774,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr std::shared_ptr pblock = std::make_shared(); vRecv >> *pblock; - LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->id); + LogPrint(BCLog::NET, "received block %s peer=%d\n", pblock->GetHash().ToString(), pfrom->GetId()); // Process all blocks from whitelisted peers, even if not requested, // unless we're still syncing with the network. @@ -2806,14 +2806,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // Making nodes which are behind NAT and can only make outgoing connections ignore // the getaddr message mitigates the attack. if (!pfrom->fInbound) { - LogPrint(BCLog::NET, "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->id); + LogPrint(BCLog::NET, "Ignoring \"getaddr\" from outbound connection. peer=%d\n", pfrom->GetId()); return true; } // Only send one GetAddr response per connection to reduce resource waste // and discourage addr stamping of INV announcements. if (pfrom->fSentAddr) { - LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->id); + LogPrint(BCLog::NET, "Ignoring repeated \"getaddr\". peer=%d\n", pfrom->GetId()); return true; } pfrom->fSentAddr = true; @@ -2914,7 +2914,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (!(sProblem.empty())) { LogPrint(BCLog::NET, "pong peer=%d: %s, %x expected, %x received, %u bytes\n", - pfrom->id, + pfrom->GetId(), sProblem, pfrom->nPingNonceSent, nonce, @@ -3027,7 +3027,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::MNLISTDIFF, mnListDiff)); } else { LogPrint(BCLog::NET, "getmnlistdiff failed for baseBlockHash=%s, blockHash=%s. error=%s\n", cmd.baseBlockHash.ToString(), cmd.blockHash.ToString(), strError); - Misbehaving(pfrom->id, 1); + Misbehaving(pfrom->GetId(), 1); } } @@ -3035,8 +3035,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr else if (strCommand == NetMsgType::MNLISTDIFF) { // we have never requested this LOCK(cs_main); - Misbehaving(pfrom->id, 100); - LogPrint(BCLog::NET, "received not-requested mnlistdiff. peer=%d\n", pfrom->id); + Misbehaving(pfrom->GetId(), 100); + LogPrint(BCLog::NET, "received not-requested mnlistdiff. peer=%d\n", pfrom->GetId()); } @@ -3077,7 +3077,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr else { // Ignore unknown commands for extensibility - LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->id); + LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId()); } } @@ -3156,7 +3156,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic& i msg.SetVersion(pfrom->GetRecvVersion()); // Scan for message start if (memcmp(msg.hdr.pchMessageStart, chainparams.MessageStart(), CMessageHeader::MESSAGE_START_SIZE) != 0) { - LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id); + LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->GetId()); pfrom->fDisconnect = true; return false; } @@ -3165,7 +3165,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic& i CMessageHeader& hdr = msg.hdr; if (!hdr.IsValid(chainparams.MessageStart())) { - LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id); + LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->GetId()); return fMoreWork; } std::string strCommand = hdr.GetCommand(); @@ -3222,7 +3222,7 @@ bool ProcessMessages(CNode* pfrom, CConnman& connman, const std::atomic& i } if (!fRet) { - LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->id); + LogPrintf("%s(%s, %u bytes) FAILED peer=%d\n", __func__, SanitizeString(strCommand), nMessageSize, pfrom->GetId()); } LOCK(cs_main); @@ -3352,7 +3352,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr got back an empty response. */ if (pindexStart->pprev) pindexStart = pindexStart->pprev; - LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->id, pto->nStartingHeight); + LogPrint(BCLog::NET, "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->nHeight, pto->GetId(), pto->nStartingHeight); connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256())); } } @@ -3382,7 +3382,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr (!state.fPreferHeaderAndIDs || pto->vBlockHashesToAnnounce.size() > 1)) || pto->vBlockHashesToAnnounce.size() > MAX_BLOCKS_TO_ANNOUNCE); const CBlockIndex *pBestIndex = NULL; // last header queued for delivery - ProcessBlockAvailability(pto->id); // ensure pindexBestKnownBlock is up-to-date + ProcessBlockAvailability(pto->GetId()); // ensure pindexBestKnownBlock is up-to-date if (!fRevertToInv) { bool fFoundStartingHeader = false; @@ -3446,7 +3446,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr // We only send up to 1 block as header-and-ids, as otherwise // probably means we're doing an initial-ish-sync or they're slow LogPrint(BCLog::NET, "%s sending header-and-ids %s to peer=%d\n", __func__, - vHeaders.front().GetHash().ToString(), pto->id); + vHeaders.front().GetHash().ToString(), pto->GetId()); bool fGotBlockFromCache = false; { @@ -3469,10 +3469,10 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr LogPrint(BCLog::NET, "%s: %u headers, range (%s, %s), to peer=%d\n", __func__, vHeaders.size(), vHeaders.front().GetHash().ToString(), - vHeaders.back().GetHash().ToString(), pto->id); + vHeaders.back().GetHash().ToString(), pto->GetId()); } else { LogPrint(BCLog::NET, "%s: sending header %s to peer=%d\n", __func__, - vHeaders.front().GetHash().ToString(), pto->id); + vHeaders.front().GetHash().ToString(), pto->GetId()); } connman.PushMessage(pto, msgMaker.Make(NetMsgType::HEADERS, vHeaders)); state.pindexBestHeaderSent = pBestIndex; @@ -3501,7 +3501,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr if (!PeerHasHeader(&state, pindex)) { pto->PushInventory(CInv(MSG_BLOCK, hashToAnnounce)); LogPrint(BCLog::NET, "%s: sending inv peer=%d hash=%s\n", __func__, - pto->id, hashToAnnounce.ToString()); + pto->GetId(), hashToAnnounce.ToString()); } } } @@ -3559,10 +3559,10 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr } pto->filterInventoryKnown.insert(hash); - LogPrint(BCLog::NET, "SendMessages -- queued inv: %s index=%d peer=%d\n", inv.ToString(), vInv.size(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- queued inv: %s index=%d peer=%d\n", inv.ToString(), vInv.size(), pto->GetId()); vInv.push_back(inv); if (vInv.size() == MAX_INV_SZ) { - LogPrint(BCLog::NET, "SendMessages -- pushing inv's: count=%d peer=%d\n", vInv.size(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- pushing inv's: count=%d peer=%d\n", vInv.size(), pto->GetId()); connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv)); vInv.clear(); } @@ -3651,7 +3651,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr // Stalling only triggers when the block download window cannot move. During normal steady state, // the download window should be much larger than the to-be-downloaded set of blocks, so disconnection // should only happen during initial block download. - LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->id); + LogPrintf("Peer=%d is stalling block download, disconnecting\n", pto->GetId()); pto->fDisconnect = true; return true; } @@ -3664,7 +3664,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr QueuedBlock &queuedBlock = state.vBlocksInFlight.front(); int nOtherPeersWithValidatedDownloads = nPeersWithValidatedDownloads - (state.nBlocksInFlightValidHeaders > 0); if (nNow > state.nDownloadingSince + consensusParams.nPowTargetSpacing * (BLOCK_DOWNLOAD_TIMEOUT_BASE + BLOCK_DOWNLOAD_TIMEOUT_PER_PEER * nOtherPeersWithValidatedDownloads)) { - LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->id); + LogPrintf("Timeout downloading block %s from peer=%d, disconnecting\n", queuedBlock.hash.ToString(), pto->GetId()); pto->fDisconnect = true; return true; } @@ -3715,7 +3715,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), - pindex->nHeight, pto->id); + pindex->nHeight, pto->GetId()); } if (state.nBlocksInFlight == 0 && staller != -1) { if (State(staller)->nStallingSince == 0) { @@ -3735,17 +3735,17 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr const CInv& inv = it->second; if (!AlreadyHave(inv)) { - LogPrint(BCLog::NET, "SendMessages -- GETDATA -- requesting inv = %s peer=%d\n", inv.ToString(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- GETDATA -- requesting inv = %s peer=%d\n", inv.ToString(), pto->GetId()); vGetData.push_back(inv); if (vGetData.size() >= 1000) { connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData)); - LogPrint(BCLog::NET, "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->GetId()); vGetData.clear(); } } else { //If we're not going to ask, don't expect a response. - LogPrint(BCLog::NET, "SendMessages -- GETDATA -- already have inv = %s peer=%d\n", inv.ToString(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- GETDATA -- already have inv = %s peer=%d\n", inv.ToString(), pto->GetId()); pto->setAskFor.erase(inv.hash); } ++it; @@ -3753,7 +3753,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr pto->vecAskFor.erase(pto->vecAskFor.begin(), it); if (!vGetData.empty()) { connman.PushMessage(pto, msgMaker.Make(NetMsgType::GETDATA, vGetData)); - LogPrint(BCLog::NET, "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->id); + LogPrint(BCLog::NET, "SendMessages -- GETDATA -- pushed size = %lu peer=%d\n", vGetData.size(), pto->GetId()); } } diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index 3ba39ffd479d..01a665b027f7 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -37,7 +37,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& if (strCommand == NetMsgType::DSQUEUE) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -68,7 +68,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { LOCK(cs_main); - Misbehaving(pfrom->id, 10); + Misbehaving(pfrom->GetId(), 10); return; } @@ -136,7 +136,7 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& if (strCommand == NetMsgType::DSSTATUSUPDATE) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSSTATUSUPDATE -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -174,7 +174,7 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& } else if (strCommand == NetMsgType::DSFINALTX) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint(BCLog::PRIVATESEND, "DSFINALTX -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSFINALTX -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -201,7 +201,7 @@ void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& } else if (strCommand == NetMsgType::DSCOMPLETE) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSCOMPLETE -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } diff --git a/src/privatesend/privatesend-server.cpp b/src/privatesend/privatesend-server.cpp index 4b08c61ae4d7..ca772b38647d 100644 --- a/src/privatesend/privatesend-server.cpp +++ b/src/privatesend/privatesend-server.cpp @@ -30,7 +30,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (strCommand == NetMsgType::DSACCEPT) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint(BCLog::PRIVATESEND, "DSACCEPT -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSACCEPT -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION))); PushStatus(pfrom, STATUS_REJECTED, ERR_VERSION, connman); return; @@ -97,7 +97,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (!lockRecv) return; if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSQUEUE -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } @@ -123,7 +123,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm if (!dsq.CheckSignature(dmn->pdmnState->pubKeyOperator.Get())) { LOCK(cs_main); - Misbehaving(pfrom->id, 10); + Misbehaving(pfrom->GetId(), 10); return; } @@ -153,7 +153,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm } else if (strCommand == NetMsgType::DSVIN) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint(BCLog::PRIVATESEND, "DSVIN -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSVIN -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION))); PushStatus(pfrom, STATUS_REJECTED, ERR_VERSION, connman); return; @@ -274,7 +274,7 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, const std::string& strComm } else if (strCommand == NetMsgType::DSSIGNFINALTX) { if (pfrom->nVersion < MIN_PRIVATESEND_PEER_PROTO_VERSION) { - LogPrint(BCLog::PRIVATESEND, "DSSIGNFINALTX -- peer=%d using obsolete version %i\n", pfrom->id, pfrom->nVersion); + LogPrint(BCLog::PRIVATESEND, "DSSIGNFINALTX -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", MIN_PRIVATESEND_PEER_PROTO_VERSION))); return; } diff --git a/src/spork.cpp b/src/spork.cpp index a414160b2a44..953db496c69c 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -133,7 +133,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, const std::string& strCommand, CD LOCK(cs_main); connman.RemoveAskFor(hash); if(!chainActive.Tip()) return; - strLogMsg = strprintf("SPORK -- hash: %s id: %d value: %10d bestHeight: %d peer=%d", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Height(), pfrom->id); + strLogMsg = strprintf("SPORK -- hash: %s id: %d value: %10d bestHeight: %d peer=%d", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Height(), pfrom->GetId()); } if (spork.nTimeSigned > GetAdjustedTime() + 2 * 60 * 60) { From 7773cf9a8786ee718a0c5f92ae9a0d52bd5cbcd9 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 7 May 2017 15:13:29 +0200 Subject: [PATCH 215/987] Merge #10171: [tests] Add node methods to test framework 4550049 Reorganize BitcoinTestFramework class (John Newbery) b7dd44c Add start and stop node methods to BitcoinTestFramework (John Newbery) b111324 move initialize_chain() and initialize_chain_clean() to be methods of BitcoinTestFramework (John Newbery) Tree-SHA512: 17e541aea8ca4c0d1189701499384e26239e2d5905de8adb0f042d3cf4c0bbed79fcaad61d563e1743bf4c62ad4915cebb4714783db839d9c53dfbbedcae6e9a --- .../test_framework/test_framework.py | 212 ++++++++++++++---- test/functional/test_framework/util.py | 84 ------- 2 files changed, 169 insertions(+), 127 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 648e790a02e8..0fe0cc93fb55 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # Copyright (c) 2014-2016 The Bitcoin Core developers +# Copyright (c) 2014-2019 The Dash Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Base class for RPC testing.""" @@ -8,29 +9,41 @@ import logging import optparse import os -import sys import shutil +import subprocess +import sys import tempfile import time from concurrent.futures import ThreadPoolExecutor from .util import ( assert_equal, - initialize_chain, - start_node, start_nodes, + PortSeed, + MAX_NODES, + bitcoind_processes, + check_json_precision, connect_nodes_bi, connect_nodes, + disable_mocktime, disconnect_nodes, + enable_coverage, + enable_mocktime, + get_mocktime, + get_rpc_proxy, + initialize_datadir, + log_filename, + p2p_port, + rpc_url, + set_node_times, + start_node, + start_nodes, + stop_node, + stop_nodes, sync_blocks, sync_mempools, sync_masternodes, - stop_nodes, - stop_node, - enable_coverage, - check_json_precision, - initialize_chain_clean, - PortSeed, + wait_for_bitcoind_start, set_cache_mocktime, set_genesis_mocktime, get_mocktime, @@ -43,6 +56,21 @@ from .authproxy import JSONRPCException class BitcoinTestFramework(object): + """Base class for a bitcoin test script. + + Individual bitcoin test scripts should subclass this class and override the following methods: + + - __init__() + - add_options() + - setup_chain() + - setup_network() + - run_test() + + The main() method should not be overridden. + + This class also contains various public and private helper methods.""" + + # Methods to override in subclass test scripts. TEST_EXIT_PASSED = 0 TEST_EXIT_FAILED = 1 @@ -53,30 +81,18 @@ def __init__(self): self.setup_clean_chain = False self.nodes = None - def run_test(self): - raise NotImplementedError - def add_options(self, parser): pass def setup_chain(self): self.log.info("Initializing test directory "+self.options.tmpdir) if self.setup_clean_chain: - initialize_chain_clean(self.options.tmpdir, self.num_nodes) + self._initialize_chain_clean(self.options.tmpdir, self.num_nodes) set_genesis_mocktime() else: - initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir) + self._initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir) set_cache_mocktime() - def stop_node(self, num_node): - stop_node(self.nodes[num_node], num_node) - - def setup_nodes(self): - extra_args = None - if hasattr(self, "extra_args"): - extra_args = self.extra_args - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) - def setup_network(self): self.setup_nodes() @@ -87,27 +103,16 @@ def setup_network(self): connect_nodes_bi(self.nodes, i, i + 1) self.sync_all() - def split_network(self): - """ - Split the network of four nodes into nodes 0/1 and 2/3. - """ - disconnect_nodes(self.nodes[1], 2) - disconnect_nodes(self.nodes[2], 1) - self.sync_all([self.nodes[:2], self.nodes[2:]]) - - def sync_all(self, node_groups=None): - if not node_groups: - node_groups = [self.nodes] + def setup_nodes(self): + extra_args = None + if hasattr(self, "extra_args"): + extra_args = self.extra_args + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) - [sync_blocks(group) for group in node_groups] - [sync_mempools(group) for group in node_groups] + def run_test(self): + raise NotImplementedError - def join_network(self): - """ - Join the (previously split) network halves together. - """ - connect_nodes_bi(self.nodes, 1, 2) - self.sync_all() + # Main function. This should not be overridden by the subclass test scripts. def main(self): @@ -209,6 +214,45 @@ def main(self): logging.shutdown() sys.exit(self.TEST_EXIT_FAILED) + # Public helper methods. These can be accessed by the subclass test scripts. + + def start_node(self, i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): + return start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr) + + def start_nodes(self, num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None): + return start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary) + + def stop_node(self, num_node): + stop_node(self.nodes[num_node], num_node) + + def stop_nodes(self): + stop_nodes(self.nodes) + + def split_network(self): + """ + Split the network of four nodes into nodes 0/1 and 2/3. + """ + disconnect_nodes(self.nodes[1], 2) + disconnect_nodes(self.nodes[2], 1) + self.sync_all([self.nodes[:2], self.nodes[2:]]) + + def join_network(self): + """ + Join the (previously split) network halves together. + """ + connect_nodes_bi(self.nodes, 1, 2) + self.sync_all() + + def sync_all(self, node_groups=None): + if not node_groups: + node_groups = [self.nodes] + + for group in node_groups: + sync_blocks(group) + sync_mempools(group) + + # Private helper methods. These should not be accessed by the subclass test scripts. + def _start_logging(self): # Add logger and logging handlers self.log = logging.getLogger('TestFramework') @@ -237,6 +281,88 @@ def _start_logging(self): rpc_handler.setLevel(logging.DEBUG) rpc_logger.addHandler(rpc_handler) + def _initialize_chain(self, test_dir, num_nodes, cachedir): + """Initialize a pre-mined blockchain for use by the test. + + Create a cache of a 200-block-long chain (with wallet) for MAX_NODES + Afterward, create num_nodes copies from the cache.""" + + assert num_nodes <= MAX_NODES + create_cache = False + for i in range(MAX_NODES): + if not os.path.isdir(os.path.join(cachedir, 'node' + str(i))): + create_cache = True + break + + if create_cache: + self.log.debug("Creating data directories from cached datadir") + + # find and delete old cache directories if any exist + for i in range(MAX_NODES): + if os.path.isdir(os.path.join(cachedir, "node" + str(i))): + shutil.rmtree(os.path.join(cachedir, "node" + str(i))) + + # Create cache directories, run dashds: + for i in range(MAX_NODES): + datadir = initialize_datadir(cachedir, i) + args = [os.getenv("DASHD", "dashd"), "-server", "-keypool=1", "-datadir=" + datadir, "-discover=0"] + if i > 0: + args.append("-connect=127.0.0.1:" + str(p2p_port(0))) + bitcoind_processes[i] = subprocess.Popen(args) + self.log.debug("initialize_chain: dashd started, waiting for RPC to come up") + wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) + self.log.debug("initialize_chain: RPC successfully started") + + self.nodes = [] + for i in range(MAX_NODES): + try: + self.nodes.append(get_rpc_proxy(rpc_url(i), i)) + except: + self.log.exception("Error connecting to node %d" % i) + sys.exit(1) + + # Create a 200-block-long chain; each of the 4 first nodes + # gets 25 mature blocks and 25 immature. + # Note: To preserve compatibility with older versions of + # initialize_chain, only 4 nodes will generate coins. + # + # blocks are created with timestamps 10 minutes apart + # starting from 2010 minutes in the past + enable_mocktime() + block_time = get_mocktime() - (201 * 10 * 60) + for i in range(2): + for peer in range(4): + for j in range(25): + set_node_times(self.nodes, block_time) + self.nodes[peer].generate(1) + block_time += 10 * 60 + # Must sync before next peer starts generating blocks + sync_blocks(self.nodes) + + # Shut them down, and clean up cache directories: + self.stop_nodes() + self.nodes = [] + disable_mocktime() + for i in range(MAX_NODES): + os.remove(log_filename(cachedir, i, "debug.log")) + os.remove(log_filename(cachedir, i, "db.log")) + os.remove(log_filename(cachedir, i, "peers.dat")) + os.remove(log_filename(cachedir, i, "fee_estimates.dat")) + + for i in range(num_nodes): + from_dir = os.path.join(cachedir, "node" + str(i)) + to_dir = os.path.join(test_dir, "node" + str(i)) + shutil.copytree(from_dir, to_dir) + initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf + + def _initialize_chain_clean(self, test_dir, num_nodes): + """Initialize empty blockchain for use by the test. + + Create an empty blockchain and num_nodes wallets. + Useful if a test case wants complete control over initialization.""" + for i in range(num_nodes): + initialize_datadir(test_dir, i) + MASTERNODE_COLLATERAL = 1000 @@ -719,7 +845,7 @@ def add_options(self, parser): help="dashd binary to use for reference nodes (if any)") def setup_network(self): - self.nodes = start_nodes( + self.nodes = self.start_nodes( self.num_nodes, self.options.tmpdir, extra_args=[['-whitelist=127.0.0.1']] * self.num_nodes, binary=[self.options.testbinary] + diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 6ef206df2f4d..343a871ff546 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -250,90 +250,6 @@ def wait_for_bitcoind_start(process, url, i): raise # unknown JSON RPC exception time.sleep(0.25) -def initialize_chain(test_dir, num_nodes, cachedir, extra_args=None, redirect_stderr=False): - """ - Create a cache of a 200-block-long chain (with wallet) for MAX_NODES - Afterward, create num_nodes copies from the cache - """ - - assert num_nodes <= MAX_NODES - create_cache = False - for i in range(MAX_NODES): - if not os.path.isdir(os.path.join(cachedir, 'node'+str(i))): - create_cache = True - break - - if create_cache: - logger.debug("Creating data directories from cached datadir") - - #find and delete old cache directories if any exist - for i in range(MAX_NODES): - if os.path.isdir(os.path.join(cachedir,"node"+str(i))): - shutil.rmtree(os.path.join(cachedir,"node"+str(i))) - - set_genesis_mocktime() - # Create cache directories, run dashds: - for i in range(MAX_NODES): - datadir=initialize_datadir(cachedir, i) - args = [ os.getenv("BITCOIND", "dashd"), "-server", "-keypool=1", "-datadir="+datadir, "-discover=0", "-mocktime="+str(GENESISTIME) ] - if i > 0: - args.append("-connect=127.0.0.1:"+str(p2p_port(0))) - if extra_args is not None: - args += extra_args - stderr = None - if redirect_stderr: - stderr = sys.stdout - bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr) - logger.debug("initialize_chain: dashd started, waiting for RPC to come up") - wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) - logger.debug("initialize_chain: RPC successfully started") - - rpcs = [] - for i in range(MAX_NODES): - try: - rpcs.append(get_rpc_proxy(rpc_url(i), i)) - except: - sys.stderr.write("Error connecting to "+url+"\n") - sys.exit(1) - - # Create a 200-block-long chain; each of the 4 first nodes - # gets 25 mature blocks and 25 immature. - # Note: To preserve compatibility with older versions of - # initialize_chain, only 4 nodes will generate coins. - # - # blocks are created with timestamps 156 seconds apart - block_time = GENESISTIME - for i in range(2): - for peer in range(4): - for j in range(25): - set_node_times(rpcs, block_time) - rpcs[peer].generate(1) - block_time += 156 - # Must sync before next peer starts generating blocks - sync_blocks(rpcs) - - # Shut them down, and clean up cache directories: - stop_nodes(rpcs) - disable_mocktime() - for i in range(MAX_NODES): - os.remove(log_filename(cachedir, i, "debug.log")) - os.remove(log_filename(cachedir, i, "db.log")) - os.remove(log_filename(cachedir, i, "peers.dat")) - os.remove(log_filename(cachedir, i, "fee_estimates.dat")) - - for i in range(num_nodes): - from_dir = os.path.join(cachedir, "node"+str(i)) - to_dir = os.path.join(test_dir, "node"+str(i)) - shutil.copytree(from_dir, to_dir) - initialize_datadir(test_dir, i) # Overwrite port/rpcport in dash.conf - -def initialize_chain_clean(test_dir, num_nodes): - """ - Create an empty blockchain and num_nodes wallets. - Useful if a test case wants complete control over initialization. - """ - for i in range(num_nodes): - datadir=initialize_datadir(test_dir, i) def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, redirect_stderr=False, stderr=None): """ From 07752f63ea18e3f50b4dfc0245a365da23d4c1ba Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 8 May 2017 19:31:49 +0200 Subject: [PATCH 216/987] Merge #10352: test: Add elapsed time to RPC tracing 20187e4 test: Add elapsed time to RPC tracing (Wladimir J. van der Laan) Tree-SHA512: f271acedd14020cf911711577f6dd940850fa84d2577618af06a2247c940fcc5b339a86c1c7a179899c556d217a6c967c785fb311bba43a9b6073cbe470b6737 --- test/functional/test_framework/authproxy.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py index 9ab3094b0674..dfcc524313a6 100644 --- a/test/functional/test_framework/authproxy.py +++ b/test/functional/test_framework/authproxy.py @@ -42,6 +42,7 @@ import json import logging import socket +import time try: import urllib.parse as urlparse except ImportError: @@ -163,6 +164,7 @@ def _batch(self, rpc_call_list): return self._request('POST', self.__url.path, postdata.encode('utf-8')) def _get_response(self): + req_start_time = time.time() try: http_response = self.__conn.getresponse() except socket.timeout as e: @@ -183,8 +185,9 @@ def _get_response(self): responsedata = http_response.read().decode('utf8') response = json.loads(responsedata, parse_float=decimal.Decimal) + elapsed = time.time() - req_start_time if "error" in response and response["error"] is None: - log.debug("<-%s- %s"%(response["id"], json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii))) + log.debug("<-%s- [%.6f] %s"%(response["id"], elapsed, json.dumps(response["result"], default=EncodeDecimal, ensure_ascii=self.ensure_ascii))) else: - log.debug("<-- "+responsedata) + log.debug("<-- [%.6f] %s"%(elapsed,responsedata)) return response From 5b99bfc6fae2891f13d58187e185bc9fb4caf6a0 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 8 May 2017 20:13:47 +0200 Subject: [PATCH 217/987] Merge #10342: [tests] Improve mempool_persist test 329ac3b [tests] use wait_until in mempool_persist.py (John Newbery) Tree-SHA512: 3f5fe3dcdb5da3b10a41f7b88d29c15b79c02fbb037914b4342b77428f2afe8b342f6adacb28a9eb5549aa156cd146175389bd61909a20df3fecb88361c4779f --- test/functional/mempool_persist.py | 41 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index c22b7ff0200a..7b15476ea271 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -6,11 +6,11 @@ By default, bitcoind will dump mempool on shutdown and then reload it on startup. This can be overridden with -the -persistmempool=false command line option. +the -persistmempool=0 command line option. Test is as follows: - - start node0, node1 and node2. node1 has -persistmempool=false + - start node0, node1 and node2. node1 has -persistmempool=0 - create 5 transactions on node2 to its own address. Note that these are not sent to node0 or node1 addresses because we don't want them to be saved in the wallet. @@ -20,17 +20,19 @@ in its mempool. Shutdown node0. This tests that by default the mempool is persistent. - startup node1. Verify that its mempool is empty. Shutdown node1. - This tests that with -persistmempool=false, the mempool is not + This tests that with -persistmempool=0, the mempool is not dumped to disk when the node is shut down. - - Restart node0 with -persistmempool=false. Verify that its mempool is - empty. Shutdown node0. This tests that with -persistmempool=false, + - Restart node0 with -persistmempool=0. Verify that its mempool is + empty. Shutdown node0. This tests that with -persistmempool=0, the mempool is not loaded from disk on start up. - - Restart node0 with -persistmempool=true. Verify that it has 5 - transactions in its mempool. This tests that -persistmempool=false + - Restart node0 with -persistmempool. Verify that it has 5 + transactions in its mempool. This tests that -persistmempool=0 does not overwrite a previously valid mempool stored on disk. """ +import time +from test_framework.mininode import wait_until from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * @@ -38,18 +40,10 @@ class MempoolPersistTest(BitcoinTestFramework): def __init__(self): super().__init__() + # We need 3 nodes for this test. Node1 does not have a persistent mempool. self.num_nodes = 3 self.setup_clean_chain = False - - def setup_network(self): - # We need 3 nodes for this test. Node1 does not have a persistent mempool. - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir, ["-persistmempool=false"])) - self.nodes.append(start_node(2, self.options.tmpdir)) - connect_nodes_bi(self.nodes, 0, 2) - connect_nodes_bi(self.nodes, 1, 2) - self.is_network_split = False + self.extra_args = [[], ["-persistmempool=0"], []] def run_test(self): chain_height = self.nodes[0].getblockcount() @@ -57,6 +51,7 @@ def run_test(self): self.log.debug("Mine a single block to get out of IBD") self.nodes[0].generate(1) + self.sync_all() self.log.debug("Send 5 transactions from node2 (to its own address)") for i in range(5): @@ -72,20 +67,24 @@ def run_test(self): self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir)) self.nodes.append(start_node(1, self.options.tmpdir)) - assert_equal(len(self.nodes[0].getrawmempool()), 5) + # Give bitcoind a second to reload the mempool + time.sleep(1) + assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) assert_equal(len(self.nodes[1].getrawmempool()), 0) - self.log.debug("Stop-start node0 with -persistmempool=false. Verify that it doesn't load its mempool.dat file.") + self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") stop_nodes(self.nodes) self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=false"])) + self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=0"])) + # Give bitcoind a second to reload the mempool + time.sleep(1) assert_equal(len(self.nodes[0].getrawmempool()), 0) self.log.debug("Stop-start node0. Verify that it has the transactions in its mempool.") stop_nodes(self.nodes) self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir)) - assert_equal(len(self.nodes[0].getrawmempool()), 5) + assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) if __name__ == '__main__': MempoolPersistTest().main() From 15f7f9c8500fdaea3cde7c85bf521f1eefe103d7 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 9 May 2017 12:58:36 +0200 Subject: [PATCH 218/987] Merge #10287: [tests] Update Unit Test for addrman.h/addrman.cpp ed36de5 [tests] Update Unit Test for addrman.h/addrman.cpp (Jimmy Song) Tree-SHA512: e7c08c19e227c34c230900e14a176b2290022b78b0ece387452e673662491c11f26249cbf1711235276c07a964c339e27b4cda9a2730ded5c0e23a650e0d72db --- src/test/addrman_tests.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 48d81d8a67b2..b3befa1947a6 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Test 2: Does Addrman::Add work as expected. CService addr1 = ResolveService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source)); BOOST_CHECK(addrman.size() == 1); CAddrInfo addr_ret1 = addrman.Select(); BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333"); @@ -99,14 +99,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Test 3: Does IP address deduplication work correctly. // Expected dup IP should not be added. CService addr1_dup = ResolveService("250.1.1.1", 8333); - addrman.Add(CAddress(addr1_dup, NODE_NONE), source); + BOOST_CHECK(!addrman.Add(CAddress(addr1_dup, NODE_NONE), source)); BOOST_CHECK(addrman.size() == 1); // Test 5: New table has one addr and we add a diff addr we should // have two addrs. CService addr2 = ResolveService("250.1.1.2", 8333); - addrman.Add(CAddress(addr2, NODE_NONE), source); + BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source)); BOOST_CHECK(addrman.size() == 2); // Test 6: AddrMan::Clear() should empty the new table. @@ -114,6 +114,13 @@ BOOST_AUTO_TEST_CASE(addrman_simple) BOOST_CHECK(addrman.size() == 0); CAddrInfo addr_null2 = addrman.Select(); BOOST_CHECK(addr_null2.ToString() == "[::]:0"); + + // Test 6.5: AddrMan::Add multiple addresses works as expected + std::vector vAddr; + vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE)); + vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE)); + BOOST_CHECK(addrman.Add(vAddr, source)); + BOOST_CHECK(addrman.size() == 2); } BOOST_AUTO_TEST_CASE(addrman_ports) @@ -398,9 +405,8 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) // Test 25: Ensure GetAddr still returns 23% when addrman has many addrs. for (unsigned int i = 1; i < (8 * 256); i++) { int octet1 = i % 256; - int octet2 = (i / 256) % 256; - int octet3 = (i / (256 * 2)) % 256; - std::string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + "." + boost::to_string(octet3) + ".23"; + int octet2 = i >> 8 % 256; + std::string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + ".1.23"; CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE); // Ensure that for all addrs in addrman, isTerrible == false. @@ -412,10 +418,10 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) std::vector vAddr = addrman.GetAddr(); size_t percent23 = (addrman.size() * 23) / 100; - BOOST_CHECK(vAddr.size() == percent23); - BOOST_CHECK(vAddr.size() == 461); + BOOST_CHECK_EQUAL(vAddr.size(), percent23); + BOOST_CHECK_EQUAL(vAddr.size(), 461); // (Addrman.size() < number of addresses added) due to address collisions. - BOOST_CHECK(addrman.size() == 2007); + BOOST_CHECK_EQUAL(addrman.size(), 2006); } @@ -493,7 +499,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash(); uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash(); + // Test 29.5: Make sure the buckets are what we expect BOOST_CHECK(info1.GetNewBucket(nKey1) == 786); + BOOST_CHECK(info1.GetNewBucket(nKey1, source1) == 786); // Test 30: Make sure key actually randomizes bucket placement. A fail on // this test could be a security issue. From b13d92079d80f73e51d6113fe0851333be3f5c16 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 9 May 2017 10:10:23 -0700 Subject: [PATCH 219/987] Merge #10322: Use hardware timestamps in RNG seeding 2c0a6f1 Use sanity check timestamps as entropy (Pieter Wuille) 33f853d Test that GetPerformanceCounter() increments (Pieter Wuille) f544094 Use hardware timestamps in RNG seeding (Pieter Wuille) Tree-SHA512: ea96ff56d425b5dc693b4dd35c8aa64ba20a01b9bd7d2d65298ece623f434e8cfa190f9c0f9b76df8aa496547bfa64533eb751edec8401d09bd5ee3478928a59 --- src/random.cpp | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index b53d5970f679..89e9871052a2 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #ifndef WIN32 #include @@ -43,15 +45,22 @@ static void RandFailure() static inline int64_t GetPerformanceCounter() { - int64_t nCounter = 0; -#ifdef WIN32 - QueryPerformanceCounter((LARGE_INTEGER*)&nCounter); + // Read the hardware time stamp counter when available. + // See https://en.wikipedia.org/wiki/Time_Stamp_Counter for more information. +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + return __rdtsc(); +#elif !defined(_MSC_VER) && defined(__i386__) + uint64_t r = 0; + __asm__ volatile ("rdtsc" : "=A"(r)); // Constrain the r variable to the eax:edx pair. + return r; +#elif !defined(_MSC_VER) && (defined(__x86_64__) || defined(__amd64__)) + uint64_t r1 = 0, r2 = 0; + __asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx. + return (r2 << 32) | r1; #else - timeval t; - gettimeofday(&t, NULL); - nCounter = (int64_t)(t.tv_sec * 1000000 + t.tv_usec); + // Fall back to using C++11 clock (usually microsecond or nanosecond precision) + return std::chrono::high_resolution_clock::now().time_since_epoch().count(); #endif - return nCounter; } void RandAddSeed() @@ -265,6 +274,8 @@ FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false) bool Random_SanityCheck() { + uint64_t start = GetPerformanceCounter(); + /* This does not measure the quality of randomness, but it does test that * OSRandom() overwrites all 32 bytes of the output given a maximum * number of tries. @@ -291,7 +302,18 @@ bool Random_SanityCheck() tries += 1; } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); - return (num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ + if (num_overwritten != NUM_OS_RANDOM_BYTES) return false; /* If this failed, bailed out after too many tries */ + + // Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep. + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + uint64_t stop = GetPerformanceCounter(); + if (stop == start) return false; + + // We called GetPerformanceCounter. Use it as entropy. + RAND_add((const unsigned char*)&start, sizeof(start), 1); + RAND_add((const unsigned char*)&stop, sizeof(stop), 1); + + return true; } FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0) From 31cc65c2ed3b59e2fe446fe04dcbe574c2fa71e9 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 9 May 2017 10:13:45 -0700 Subject: [PATCH 220/987] Merge #10338: Maintain state across GetStrongRandBytes calls 97477c5 Maintain state across GetStrongRandBytes calls (Pieter Wuille) Tree-SHA512: 77e9b1f3c6eeb0c2a3e0c64358150767222ff0b7120ccd5f4ae0276cea0e4fa275c1b757e3f20be07dc0b4ef07f70ab0b70112080c8d3d0cb6ed703db8a59168 --- src/random.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/random.cpp b/src/random.cpp index 89e9871052a2..3c47feb1a212 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -34,6 +34,8 @@ #include #endif +#include + #include #include @@ -201,6 +203,10 @@ void GetRandBytes(unsigned char* buf, int num) } } +static std::mutex cs_rng_state; +static unsigned char rng_state[32] = {0}; +static uint64_t rng_counter = 0; + void GetStrongRandBytes(unsigned char* out, int num) { assert(num <= 32); @@ -216,8 +222,17 @@ void GetStrongRandBytes(unsigned char* out, int num) GetOSRand(buf); hasher.Write(buf, 32); + // Combine with and update state + { + std::unique_lock lock(cs_rng_state); + hasher.Write(rng_state, sizeof(rng_state)); + hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter)); + ++rng_counter; + hasher.Finalize(buf); + memcpy(rng_state, buf + 32, 32); + } + // Produce output - hasher.Finalize(buf); memcpy(out, buf, num); memory_cleanse(buf, 64); } From 1c7ec5f4adc55f4e441be3e652de9925787ea7c9 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 9 May 2017 23:15:15 +0200 Subject: [PATCH 221/987] Merge #10361: qa: disablewallet: Check that wallet is really disabled fa7396d qa: disablewallet: Check that wallet is really disabled (MarcoFalke) Tree-SHA512: 8c999ae0763fad389ba06f23cca3f589edaaf6dabd29ea8493413eee574ef2c1d49a69cb1158d8b28254cf922277a86b45747e50f44ebc9b0545297c3987289d --- test/functional/disablewallet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/disablewallet.py b/test/functional/disablewallet.py index 94d4402ea220..0a8c74dc1e23 100755 --- a/test/functional/disablewallet.py +++ b/test/functional/disablewallet.py @@ -21,7 +21,8 @@ def __init__(self): self.extra_args = [["-disablewallet"]] def run_test (self): - # Check regression: https://github.com/bitcoin/bitcoin/issues/6963#issuecomment-154548880 + # Make sure wallet is really disabled + assert_raises_jsonrpc(-32601, 'Method not found', self.nodes[0].getwalletinfo) x = self.nodes[0].validateaddress('7TSBtVu959hGEGPKyHjJz9k55RpWrPffXz') assert(x['isvalid'] == False) x = self.nodes[0].validateaddress('ycwedq2f3sz2Yf9JqZsBCQPxp18WU3Hp4J') From cbb7a8ecc0dcff0318e9aa9e01524835a4cff578 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 9 May 2017 23:23:40 +0200 Subject: [PATCH 222/987] Merge #10371: [tests] Clean up addrman_tests.cpp a80f295 [tests] Clean up addrman_tests.cpp (Jimmy Song) Tree-SHA512: c745ebb0b8867e8abacfab62561a883ee5219176951e9ad4821fdc1e6152c9548663824ad624bfce1294760284fc6bd2a598749d66e62af55f39c59a1ea357ce --- src/test/addrman_tests.cpp | 177 ++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 90 deletions(-) diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index b3befa1947a6..ed690bcfdc2a 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -84,43 +84,43 @@ BOOST_AUTO_TEST_CASE(addrman_simple) CNetAddr source = ResolveIP("252.2.2.2"); - // Test 1: Does Addrman respond correctly when empty. - BOOST_CHECK(addrman.size() == 0); + // Test: Does Addrman respond correctly when empty. + BOOST_CHECK_EQUAL(addrman.size(), 0); CAddrInfo addr_null = addrman.Select(); - BOOST_CHECK(addr_null.ToString() == "[::]:0"); + BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0"); - // Test 2: Does Addrman::Add work as expected. + // Test: Does Addrman::Add work as expected. CService addr1 = ResolveService("250.1.1.1", 8333); BOOST_CHECK(addrman.Add(CAddress(addr1, NODE_NONE), source)); - BOOST_CHECK(addrman.size() == 1); + BOOST_CHECK_EQUAL(addrman.size(), 1); CAddrInfo addr_ret1 = addrman.Select(); - BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333"); + BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333"); - // Test 3: Does IP address deduplication work correctly. + // Test: Does IP address deduplication work correctly. // Expected dup IP should not be added. CService addr1_dup = ResolveService("250.1.1.1", 8333); BOOST_CHECK(!addrman.Add(CAddress(addr1_dup, NODE_NONE), source)); - BOOST_CHECK(addrman.size() == 1); + BOOST_CHECK_EQUAL(addrman.size(), 1); - // Test 5: New table has one addr and we add a diff addr we should + // Test: New table has one addr and we add a diff addr we should // have two addrs. CService addr2 = ResolveService("250.1.1.2", 8333); BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source)); - BOOST_CHECK(addrman.size() == 2); + BOOST_CHECK_EQUAL(addrman.size(), 2); - // Test 6: AddrMan::Clear() should empty the new table. + // Test: AddrMan::Clear() should empty the new table. addrman.Clear(); - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); CAddrInfo addr_null2 = addrman.Select(); - BOOST_CHECK(addr_null2.ToString() == "[::]:0"); + BOOST_CHECK_EQUAL(addr_null2.ToString(), "[::]:0"); - // Test 6.5: AddrMan::Add multiple addresses works as expected + // Test: AddrMan::Add multiple addresses works as expected std::vector vAddr; vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE)); vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE)); BOOST_CHECK(addrman.Add(vAddr, source)); - BOOST_CHECK(addrman.size() == 2); + BOOST_CHECK_EQUAL(addrman.size(), 2); } BOOST_AUTO_TEST_CASE(addrman_ports) @@ -132,26 +132,26 @@ BOOST_AUTO_TEST_CASE(addrman_ports) CNetAddr source = ResolveIP("252.2.2.2"); - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); // Test 7; Addr with same IP but diff port does not replace existing addr. CService addr1 = ResolveService("250.1.1.1", 8333); addrman.Add(CAddress(addr1, NODE_NONE), source); - BOOST_CHECK(addrman.size() == 1); + BOOST_CHECK_EQUAL(addrman.size(), 1); CService addr1_port = ResolveService("250.1.1.1", 8334); addrman.Add(CAddress(addr1_port, NODE_NONE), source); - BOOST_CHECK(addrman.size() == 1); + BOOST_CHECK_EQUAL(addrman.size(), 1); CAddrInfo addr_ret2 = addrman.Select(); - BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333"); + BOOST_CHECK_EQUAL(addr_ret2.ToString(), "250.1.1.1:8333"); - // Test 8: Add same IP but diff port to tried table, it doesn't get added. + // Test: Add same IP but diff port to tried table, it doesn't get added. // Perhaps this is not ideal behavior but it is the current behavior. addrman.Good(CAddress(addr1_port, NODE_NONE)); - BOOST_CHECK(addrman.size() == 1); + BOOST_CHECK_EQUAL(addrman.size(), 1); bool newOnly = true; CAddrInfo addr_ret3 = addrman.Select(newOnly); - BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333"); + BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333"); } @@ -164,25 +164,25 @@ BOOST_AUTO_TEST_CASE(addrman_select) CNetAddr source = ResolveIP("252.2.2.2"); - // Test 9: Select from new with 1 addr in new. + // Test: Select from new with 1 addr in new. CService addr1 = ResolveService("250.1.1.1", 8333); addrman.Add(CAddress(addr1, NODE_NONE), source); - BOOST_CHECK(addrman.size() == 1); + BOOST_CHECK_EQUAL(addrman.size(), 1); bool newOnly = true; CAddrInfo addr_ret1 = addrman.Select(newOnly); - BOOST_CHECK(addr_ret1.ToString() == "250.1.1.1:8333"); + BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333"); - // Test 10: move addr to tried, select from new expected nothing returned. + // Test: move addr to tried, select from new expected nothing returned. addrman.Good(CAddress(addr1, NODE_NONE)); - BOOST_CHECK(addrman.size() == 1); + BOOST_CHECK_EQUAL(addrman.size(), 1); CAddrInfo addr_ret2 = addrman.Select(newOnly); - BOOST_CHECK(addr_ret2.ToString() == "[::]:0"); + BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0"); CAddrInfo addr_ret3 = addrman.Select(); - BOOST_CHECK(addr_ret3.ToString() == "250.1.1.1:8333"); + BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333"); - BOOST_CHECK(addrman.size() == 1); + BOOST_CHECK_EQUAL(addrman.size(), 1); // Add three addresses to new table. @@ -206,10 +206,10 @@ BOOST_AUTO_TEST_CASE(addrman_select) addrman.Add(CAddress(addr7, NODE_NONE), ResolveService("250.1.1.3", 8333)); addrman.Good(CAddress(addr7, NODE_NONE)); - // Test 11: 6 addrs + 1 addr from last test = 7. - BOOST_CHECK(addrman.size() == 7); + // Test: 6 addrs + 1 addr from last test = 7. + BOOST_CHECK_EQUAL(addrman.size(), 7); - // Test 12: Select pulls from new and tried regardless of port number. + // Test: Select pulls from new and tried regardless of port number. std::set ports; for (int i = 0; i < 20; ++i) { ports.insert(addrman.Select().GetPort()); @@ -226,24 +226,24 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions) CNetAddr source = ResolveIP("252.2.2.2"); - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); for (unsigned int i = 1; i < 18; i++) { CService addr = ResolveService("250.1.1." + boost::to_string(i)); addrman.Add(CAddress(addr, NODE_NONE), source); - //Test 13: No collision in new table yet. - BOOST_CHECK(addrman.size() == i); + //Test: No collision in new table yet. + BOOST_CHECK_EQUAL(addrman.size(), i); } - //Test 14: new table collision! + //Test: new table collision! CService addr1 = ResolveService("250.1.1.18"); addrman.Add(CAddress(addr1, NODE_NONE), source); - BOOST_CHECK(addrman.size() == 17); + BOOST_CHECK_EQUAL(addrman.size(), 17); CService addr2 = ResolveService("250.1.1.19"); addrman.Add(CAddress(addr2, NODE_NONE), source); - BOOST_CHECK(addrman.size() == 18); + BOOST_CHECK_EQUAL(addrman.size(), 18); } BOOST_AUTO_TEST_CASE(addrman_tried_collisions) @@ -255,25 +255,25 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions) CNetAddr source = ResolveIP("252.2.2.2"); - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); for (unsigned int i = 1; i < 80; i++) { CService addr = ResolveService("250.1.1." + boost::to_string(i)); addrman.Add(CAddress(addr, NODE_NONE), source); addrman.Good(CAddress(addr, NODE_NONE)); - //Test 15: No collision in tried table yet. + //Test: No collision in tried table yet. BOOST_CHECK_EQUAL(addrman.size(), i); } - //Test 16: tried table collision! + //Test: tried table collision! CService addr1 = ResolveService("250.1.1.80"); addrman.Add(CAddress(addr1, NODE_NONE), source); - BOOST_CHECK(addrman.size() == 79); + BOOST_CHECK_EQUAL(addrman.size(), 79); CService addr2 = ResolveService("250.1.1.81"); addrman.Add(CAddress(addr2, NODE_NONE), source); - BOOST_CHECK(addrman.size() == 80); + BOOST_CHECK_EQUAL(addrman.size(), 80); } BOOST_AUTO_TEST_CASE(addrman_find) @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(addrman_find) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE); @@ -296,23 +296,20 @@ BOOST_AUTO_TEST_CASE(addrman_find) addrman.Add(addr2, source2); addrman.Add(addr3, source1); - // Test 17: ensure Find returns an IP matching what we searched on. + // Test: ensure Find returns an IP matching what we searched on. CAddrInfo* info1 = addrman.Find(addr1); - BOOST_CHECK(info1); - if (info1) - BOOST_CHECK(info1->ToString() == "250.1.2.1:8333"); + BOOST_REQUIRE(info1); + BOOST_CHECK_EQUAL(info1->ToString(), "250.1.2.1:8333"); // Test 18; Find does not discriminate by port number. CAddrInfo* info2 = addrman.Find(addr2); - BOOST_CHECK(info2); - if (info2 && info1) - BOOST_CHECK(info2->ToString() == info1->ToString()); + BOOST_REQUIRE(info2); + BOOST_CHECK_EQUAL(info2->ToString(), info1->ToString()); - // Test 19: Find returns another IP matching what we searched on. + // Test: Find returns another IP matching what we searched on. CAddrInfo* info3 = addrman.Find(addr3); - BOOST_CHECK(info3); - if (info3) - BOOST_CHECK(info3->ToString() == "251.255.2.1:8333"); + BOOST_REQUIRE(info3); + BOOST_CHECK_EQUAL(info3->ToString(), "251.255.2.1:8333"); } BOOST_AUTO_TEST_CASE(addrman_create) @@ -322,7 +319,7 @@ BOOST_AUTO_TEST_CASE(addrman_create) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); @@ -330,11 +327,11 @@ BOOST_AUTO_TEST_CASE(addrman_create) int nId; CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId); - // Test 20: The result should be the same as the input addr. - BOOST_CHECK(pinfo->ToString() == "250.1.2.1:8333"); + // Test: The result should be the same as the input addr. + BOOST_CHECK_EQUAL(pinfo->ToString(), "250.1.2.1:8333"); CAddrInfo* info2 = addrman.Find(addr1); - BOOST_CHECK(info2->ToString() == "250.1.2.1:8333"); + BOOST_CHECK_EQUAL(info2->ToString(), "250.1.2.1:8333"); } @@ -345,7 +342,7 @@ BOOST_AUTO_TEST_CASE(addrman_delete) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE); CNetAddr source1 = ResolveIP("250.1.2.1"); @@ -353,10 +350,10 @@ BOOST_AUTO_TEST_CASE(addrman_delete) int nId; addrman.Create(addr1, source1, &nId); - // Test 21: Delete should actually delete the addr. - BOOST_CHECK(addrman.size() == 1); + // Test: Delete should actually delete the addr. + BOOST_CHECK_EQUAL(addrman.size(), 1); addrman.Delete(nId); - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); CAddrInfo* info2 = addrman.Find(addr1); BOOST_CHECK(info2 == NULL); } @@ -368,11 +365,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) // Set addrman addr placement to be deterministic. addrman.MakeDeterministic(); - // Test 22: Sanity check, GetAddr should never return anything if addrman + // Test: Sanity check, GetAddr should never return anything if addrman // is empty. - BOOST_CHECK(addrman.size() == 0); + BOOST_CHECK_EQUAL(addrman.size(), 0); std::vector vAddr1 = addrman.GetAddr(); - BOOST_CHECK(vAddr1.size() == 0); + BOOST_CHECK_EQUAL(vAddr1.size(), 0); CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE); addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false @@ -387,7 +384,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) CNetAddr source1 = ResolveIP("250.1.2.1"); CNetAddr source2 = ResolveIP("250.2.3.3"); - // Test 23: Ensure GetAddr works with new addresses. + // Test: Ensure GetAddr works with new addresses. addrman.Add(addr1, source1); addrman.Add(addr2, source2); addrman.Add(addr3, source1); @@ -395,20 +392,20 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr) addrman.Add(addr5, source1); // GetAddr returns 23% of addresses, 23% of 5 is 1 rounded down. - BOOST_CHECK(addrman.GetAddr().size() == 1); + BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1); - // Test 24: Ensure GetAddr works with new and tried addresses. + // Test: Ensure GetAddr works with new and tried addresses. addrman.Good(CAddress(addr1, NODE_NONE)); addrman.Good(CAddress(addr2, NODE_NONE)); - BOOST_CHECK(addrman.GetAddr().size() == 1); + BOOST_CHECK_EQUAL(addrman.GetAddr().size(), 1); - // Test 25: Ensure GetAddr still returns 23% when addrman has many addrs. + // Test: Ensure GetAddr still returns 23% when addrman has many addrs. for (unsigned int i = 1; i < (8 * 256); i++) { int octet1 = i % 256; int octet2 = i >> 8 % 256; std::string strAddr = boost::to_string(octet1) + "." + boost::to_string(octet2) + ".1.23"; CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE); - + // Ensure that for all addrs in addrman, isTerrible == false. addr.nTime = GetAdjustedTime(); addrman.Add(addr, ResolveIP(strAddr)); @@ -444,13 +441,13 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash(); - BOOST_CHECK(info1.GetTriedBucket(nKey1) == 40); + BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1), 40); - // Test 26: Make sure key actually randomizes bucket placement. A fail on + // Test: Make sure key actually randomizes bucket placement. A fail on // this test could be a security issue. BOOST_CHECK(info1.GetTriedBucket(nKey1) != info1.GetTriedBucket(nKey2)); - // Test 27: Two addresses with same IP but different ports can map to + // Test: Two addresses with same IP but different ports can map to // different buckets because they have different keys. CAddrInfo info2 = CAddrInfo(addr2, source1); @@ -465,9 +462,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) int bucket = infoi.GetTriedBucket(nKey1); buckets.insert(bucket); } - // Test 28: IP addresses in the same group (\16 prefix for IPv4) should + // Test: IP addresses in the same group (\16 prefix for IPv4) should // never get more than 8 buckets - BOOST_CHECK(buckets.size() == 8); + BOOST_CHECK_EQUAL(buckets.size(), 8); buckets.clear(); for (int j = 0; j < 255; j++) { @@ -477,9 +474,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket) int bucket = infoj.GetTriedBucket(nKey1); buckets.insert(bucket); } - // Test 29: IP addresses in the different groups should map to more than + // Test: IP addresses in the different groups should map to more than // 8 buckets. - BOOST_CHECK(buckets.size() == 160); + BOOST_CHECK_EQUAL(buckets.size(), 160); } BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) @@ -499,18 +496,18 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash(); uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash(); - // Test 29.5: Make sure the buckets are what we expect - BOOST_CHECK(info1.GetNewBucket(nKey1) == 786); - BOOST_CHECK(info1.GetNewBucket(nKey1, source1) == 786); + // Test: Make sure the buckets are what we expect + BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), 786); + BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1), 786); - // Test 30: Make sure key actually randomizes bucket placement. A fail on + // Test: Make sure key actually randomizes bucket placement. A fail on // this test could be a security issue. BOOST_CHECK(info1.GetNewBucket(nKey1) != info1.GetNewBucket(nKey2)); - // Test 31: Ports should not effect bucket placement in the addr + // Test: Ports should not effect bucket placement in the addr CAddrInfo info2 = CAddrInfo(addr2, source1); BOOST_CHECK(info1.GetKey() != info2.GetKey()); - BOOST_CHECK(info1.GetNewBucket(nKey1) == info2.GetNewBucket(nKey1)); + BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1), info2.GetNewBucket(nKey1)); std::set buckets; for (int i = 0; i < 255; i++) { @@ -520,9 +517,9 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) int bucket = infoi.GetNewBucket(nKey1); buckets.insert(bucket); } - // Test 32: IP addresses in the same group (\16 prefix for IPv4) should + // Test: IP addresses in the same group (\16 prefix for IPv4) should // always map to the same bucket. - BOOST_CHECK(buckets.size() == 1); + BOOST_CHECK_EQUAL(buckets.size(), 1); buckets.clear(); for (int j = 0; j < 4 * 255; j++) { @@ -533,7 +530,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); } - // Test 33: IP addresses in the same source groups should map to no more + // Test: IP addresses in the same source groups should map to no more // than 64 buckets. BOOST_CHECK(buckets.size() <= 64); @@ -545,7 +542,7 @@ BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket) int bucket = infoj.GetNewBucket(nKey1); buckets.insert(bucket); } - // Test 34: IP addresses in the different source groups should map to more + // Test: IP addresses in the different source groups should map to more // than 64 buckets. BOOST_CHECK(buckets.size() > 64); } From 32c0e0f9b1db1ac9931f085706fb88475c9d1bb3 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 10 May 2017 17:16:14 +0200 Subject: [PATCH 223/987] Merge #10325: 0.15.0 Depends Updates 355c116 [depends] dbus 1.10.18 (fanquake) a8d7474 [depends] ccache 3.3.4 (fanquake) daeb767 [depends] libevent 2.1.8-stable (fanquake) d78269a [depends] Boost 1.64.0 (fanquake) 7d92c6f [depends] Latest config.guess and config.sub (fanquake) Tree-SHA512: c63cdffabb1f57b7efd71c85f845c30ce00cda56f6d665f935674f3324563a7364f3bc30c105a1ee1064f1d24eb7345d7e44791cd471094dcc5e20f307fec4cb --- depends/config.guess | 12 ++++++++---- depends/config.sub | 14 +++++++++++--- depends/packages/boost.mk | 6 +++--- depends/packages/dbus.mk | 6 +++--- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/depends/config.guess b/depends/config.guess index bbd48b60e88b..69ed3e573bb3 100755 --- a/depends/config.guess +++ b/depends/config.guess @@ -2,7 +2,7 @@ # Attempt to guess a canonical system name. # Copyright 1992-2017 Free Software Foundation, Inc. -timestamp='2017-01-01' +timestamp='2017-03-05' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -837,10 +837,11 @@ EOF UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin @@ -1343,6 +1344,9 @@ EOF NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; + NSX-?:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk${UNAME_RELEASE} + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; diff --git a/depends/config.sub b/depends/config.sub index 7e792b4ae17b..40ea5dfe1152 100755 --- a/depends/config.sub +++ b/depends/config.sub @@ -2,7 +2,7 @@ # Configuration validation subroutine script. # Copyright 1992-2017 Free Software Foundation, Inc. -timestamp='2017-01-01' +timestamp='2017-04-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -263,7 +263,7 @@ case $basic_machine in | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ @@ -315,6 +315,7 @@ case $basic_machine in | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ + | wasm32 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) @@ -388,7 +389,7 @@ case $basic_machine in | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ @@ -446,6 +447,7 @@ case $basic_machine in | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -948,6 +950,9 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -1243,6 +1248,9 @@ case $basic_machine in basic_machine=a29k-wrs os=-vxworks ;; + wasm32) + basic_machine=wasm32-unknown + ;; w65*) basic_machine=w65-wdc os=-none diff --git a/depends/packages/boost.mk b/depends/packages/boost.mk index 57d96e482129..bf773ccd147d 100644 --- a/depends/packages/boost.mk +++ b/depends/packages/boost.mk @@ -1,8 +1,8 @@ package=boost -$(package)_version=1_63_0 -$(package)_download_path=https://sourceforge.net/projects/boost/files/boost/1.63.0 +$(package)_version=1_64_0 +$(package)_download_path=https://dl.bintray.com/boostorg/release/1.64.0/source/ $(package)_file_name=$(package)_$($(package)_version).tar.bz2 -$(package)_sha256_hash=beae2529f759f6b3bf3f4969a19c2e9d6f0c503edcb2de4a61d1428519fcb3b0 +$(package)_sha256_hash=7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332 define $(package)_set_vars $(package)_config_opts_release=variant=release diff --git a/depends/packages/dbus.mk b/depends/packages/dbus.mk index 90ddcb923f21..bbe03754099f 100644 --- a/depends/packages/dbus.mk +++ b/depends/packages/dbus.mk @@ -1,8 +1,8 @@ package=dbus -$(package)_version=1.10.14 -$(package)_download_path=http://dbus.freedesktop.org/releases/dbus +$(package)_version=1.10.18 +$(package)_download_path=https://dbus.freedesktop.org/releases/dbus $(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=23238f70353e38ce5ca183ebc9525c0d97ac00ef640ad29cf794782af6e6a083 +$(package)_sha256_hash=6049ddd5f3f3e2618f615f1faeda0a115104423a7996b7aa73e2f36e38cc514a $(package)_dependencies=expat define $(package)_set_vars From 5e796e95fd32ff25a25bcbd80d2df44d1551dcbb Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 11 May 2017 07:17:10 +0200 Subject: [PATCH 224/987] Merge #10381: Shadowing warnings are not enabled by default, update doc accordingly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit f203ecc Shadowing is not enabled by default, update doc accordingly. (Pavel Janík) Tree-SHA512: a7170827caa9d35457356808445ef2387fd2edde72fb76c6241cfd5decad218558b307d223e86bb66041576b638f90f6efa8a46ea6208d43da275a993617c997 --- doc/developer-notes.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 6374637fe79d..0be01417ef3c 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -346,10 +346,9 @@ Strings and formatting Variable names -------------- -The shadowing warning (`-Wshadow`) is enabled by default. It prevents issues rising -from using a different variable with the same name. - -Please name variables so that their names do not shadow variables defined in the source code. +Although the shadowing warning (`-Wshadow`) is not enabled by default (it prevents issues rising +from using a different variable with the same name), +please name variables so that their names do not shadow variables defined in the source code. E.g. in member initializers, prepend `_` to the argument name shadowing the member name: From 6b9e864a084a5cb528498e725eca9b83737e7c8e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 12 Apr 2017 00:57:20 +0200 Subject: [PATCH 225/987] Merge #10187: tests: Fix test_runner return value in case of skipped test e96462f tests: Fix test_runner return value in case of skipped test (Wladimir J. van der Laan) Tree-SHA512: 99434ce3e0b5376268d33cdbae46d48786feb9820c7f8acccdd50f6674e315abffc84ba1feda441332d140a7480070eba732abae8f07293984d4daa9352ee8ee --- test/functional/test_runner.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 2402ccd05006..a07401db8999 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -318,7 +318,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal logging.debug("Cleaning up coverage data") coverage.cleanup() - all_passed = all(map(lambda test_result: test_result.status == "Passed", test_results)) + all_passed = all(map(lambda test_result: test_result.was_successful, test_results)) sys.exit(not all_passed) @@ -330,7 +330,7 @@ def print_results(test_results, max_len_name, runtime): time_sum = 0 for test_result in test_results: - all_passed = all_passed and test_result.status != "Failed" + all_passed = all_passed and test_result.was_successful time_sum += test_result.time test_result.padding = max_len_name results += str(test_result) @@ -418,6 +418,10 @@ def __repr__(self): return color[1] + "%s | %s%s | %s s\n" % (self.name.ljust(self.padding), glyph, self.status.ljust(7), self.time) + color[0] + @property + def was_successful(self): + return self.status != "Failed" + def check_script_list(src_dir): """Check scripts directory. From 70a164fd8af523055aeab0b198ee0be8246249e4 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 12 Apr 2017 17:48:58 +0200 Subject: [PATCH 226/987] Merge #10150: [rpc] Add logging rpc 7fd50c3 allow libevent logging to be updated during runtime (John Newbery) 5255aca [rpc] Add logging RPC (John Newbery) 4d9950d Set BCLog::LIBEVENT correctly for old libevent versions. (John Newbery) Tree-SHA512: d6788a7205372c0528da71eca052910dfb055f2940ca884f422ff3db66e23a2b49c6a15b8f27d5255554fe5c5a928f5dd903fdc63b0bd6c8fa7783e77bb30fe8 --- src/Makefile.test.include | 2 +- src/httpserver.cpp | 28 +++++++++++----- src/httpserver.h | 4 +++ src/rpc/client.cpp | 3 ++ src/rpc/misc.cpp | 69 +++++++++++++++++++++++++++++++++++++++ src/util.cpp | 20 ++++++++++-- src/util.h | 13 ++++++-- 7 files changed, 125 insertions(+), 14 deletions(-) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 1424a3fce507..e3dcb433ac14 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -111,7 +111,7 @@ endif test_test_dash_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_dash_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) test_test_dash_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BACKTRACE_LIB) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) + $(BACKTRACE_LIB) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_dash_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) if ENABLE_WALLET test_test_dash_LDADD += $(LIBBITCOIN_WALLET) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 80da394fe6a0..696fc0c14b61 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -386,15 +386,13 @@ bool InitHTTPServer() // Redirect libevent's logging to our own log event_set_log_callback(&libevent_log_cb); -#if LIBEVENT_VERSION_NUMBER >= 0x02010100 - // If -debug=libevent, set full libevent debugging. - // Otherwise, disable all libevent debugging. - if (LogAcceptCategory(BCLog::LIBEVENT)) { - event_enable_debug_logging(EVENT_DBG_ALL); - } else { - event_enable_debug_logging(EVENT_DBG_NONE); + // Update libevent's log handling. Returns false if our version of + // libevent doesn't support debug logging, in which case we should + // clear the BCLog::LIBEVENT flag. + if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) { + logCategories &= ~BCLog::LIBEVENT; } -#endif + #ifdef WIN32 evthread_use_windows_threads(); #else @@ -437,6 +435,20 @@ bool InitHTTPServer() return true; } +bool UpdateHTTPServerLogging(bool enable) { +#if LIBEVENT_VERSION_NUMBER >= 0x02010100 + if (enable) { + event_enable_debug_logging(EVENT_DBG_ALL); + } else { + event_enable_debug_logging(EVENT_DBG_NONE); + } + return true; +#else + // Can't update libevent logging if version < 02010100 + return false; +#endif +} + std::thread threadHTTP; std::future threadResult; diff --git a/src/httpserver.h b/src/httpserver.h index 49d67f4b8842..d9b45f076d64 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -32,6 +32,10 @@ void InterruptHTTPServer(); /** Stop HTTP server */ void StopHTTPServer(); +/** Change logging level for libevent. Removes BCLog::LIBEVENT from logCategories if + * libevent doesn't support debug logging.*/ +bool UpdateHTTPServerLogging(bool enable); + /** Handler for requests to a certain HTTP path */ typedef std::function HTTPRequestHandler; /** Register handler for prefix. diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 05455a032b33..2350bae88e40 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -21,6 +21,7 @@ class CRPCConvertParam int paramIdx; //!< 0-based idx of param to convert std::string paramName; //!< parameter name }; + /** * Specify a (method, idx, name) here if the argument is a non-string RPC * argument and needs to be converted from JSON. @@ -144,6 +145,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "setprivatesendamount", 0, "amount" }, { "getmempoolancestors", 1, "verbose" }, { "getmempooldescendants", 1, "verbose" }, + { "logging", 0, "include" }, + { "logging", 1, "exclude" }, { "spork", 1, "value" }, { "voteraw", 1, "tx_index" }, { "voteraw", 5, "time" }, diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 807a6c86a28b..cda3bb206033 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -8,6 +8,7 @@ #include "chain.h" #include "clientversion.h" #include "init.h" +#include "httpserver.h" #include "net.h" #include "netbase.h" #include "rpc/blockchain.h" @@ -1189,6 +1190,73 @@ UniValue getmemoryinfo(const JSONRPCRequest& request) } } +uint32_t getCategoryMask(UniValue cats) { + cats = cats.get_array(); + uint32_t mask = 0; + for (unsigned int i = 0; i < cats.size(); ++i) { + uint32_t flag = 0; + std::string cat = cats[i].get_str(); + if (!GetLogCategory(&flag, &cat)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); + } + mask |= flag; + } + return mask; +} + +UniValue logging(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() > 2) { + throw std::runtime_error( + "logging [include,...] \n" + "Gets and sets the logging configuration.\n" + "When called without an argument, returns the list of categories that are currently being debug logged.\n" + "When called with arguments, adds or removes categories from debug logging.\n" + "The valid logging categories are: " + ListLogCategories() + "\n" + "libevent logging is configured on startup and cannot be modified by this RPC during runtime." + "Arguments:\n" + "1. \"include\" (array of strings) add debug logging for these categories.\n" + "2. \"exclude\" (array of strings) remove debug logging for these categories.\n" + "\nResult: (string): a list of the logging categories that are active.\n" + "\nExamples:\n" + + HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") + + HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"") + ); + } + + uint32_t originalLogCategories = logCategories; + if (request.params.size() > 0 && request.params[0].isArray()) { + logCategories |= getCategoryMask(request.params[0]); + } + + if (request.params.size() > 1 && request.params[1].isArray()) { + logCategories &= ~getCategoryMask(request.params[1]); + } + + // Update libevent logging if BCLog::LIBEVENT has changed. + // If the library version doesn't allow it, UpdateHTTPServerLogging() returns false, + // in which case we should clear the BCLog::LIBEVENT flag. + // Throw an error if the user has explicitly asked to change only the libevent + // flag and it failed. + uint32_t changedLogCategories = originalLogCategories ^ logCategories; + if (changedLogCategories & BCLog::LIBEVENT) { + if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) { + logCategories &= ~BCLog::LIBEVENT; + if (changedLogCategories == BCLog::LIBEVENT) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1."); + } + } + } + + UniValue result(UniValue::VOBJ); + std::vector vLogCatActive = ListActiveLogCategories(); + for (const auto& logCatActive : vLogCatActive) { + result.pushKV(logCatActive.category, logCatActive.active); + } + + return result; +} + UniValue echo(const JSONRPCRequest& request) { if (request.fHelp) @@ -1229,6 +1297,7 @@ static const CRPCCommand commands[] = { "hidden", "setmocktime", &setmocktime, true, {"timestamp"}}, { "hidden", "echo", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, { "hidden", "echojson", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}}, + { "hidden", "logging", &logging, true, {"include", "exclude"}}, }; void RegisterMiscRPCCommands(CRPCTable &t) diff --git a/src/util.cpp b/src/util.cpp index 833f79fe2b5a..6f1407f8025a 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -28,7 +28,6 @@ #include #endif - #ifndef WIN32 // for posix_fallocate #ifdef __linux__ @@ -125,7 +124,7 @@ bool fLogIPs = DEFAULT_LOGIPS; std::atomic fReopenDebugLog(false); CTranslationInterface translationInterface; -/** Log categories bitfield. Leveldb/libevent need special handling if their flags are changed at runtime. */ +/** Log categories bitfield. */ std::atomic logCategories(0); /** Init OpenSSL library multithreading support */ @@ -332,7 +331,22 @@ std::string ListLogCategories() return ret; } -std::string ListActiveLogCategories() +std::vector ListActiveLogCategories() +{ + std::vector ret; + for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) { + // Omit the special cases. + if (LogCategories[i].flag != BCLog::NONE && LogCategories[i].flag != BCLog::ALL) { + CLogCategoryActive catActive; + catActive.category = LogCategories[i].category; + catActive.active = LogAcceptCategory(LogCategories[i].flag); + ret.push_back(catActive); + } + } + return ret; +} + +std::string ListActiveLogCategoriesString() { if (logCategories == BCLog::NONE) return "0"; diff --git a/src/util.h b/src/util.h index fb8033d8c97b..5b4d2df2e3fa 100644 --- a/src/util.h +++ b/src/util.h @@ -91,6 +91,12 @@ inline std::string _(const char* psz) void SetupEnvironment(); bool SetupNetworking(); +struct CLogCategoryActive +{ + std::string category; + bool active; +}; + namespace BCLog { enum LogFlags : uint64_t { NONE = 0, @@ -139,11 +145,14 @@ static inline bool LogAcceptCategory(uint64_t category) return (logCategories.load(std::memory_order_relaxed) & category) != 0; } -/** Returns a string with the supported log categories */ +/** Returns a string with the log categories. */ std::string ListLogCategories(); /** Returns a string with the list of active log categories */ -std::string ListActiveLogCategories(); +std::string ListActiveLogCategoriesString(); + +/** Returns a vector of the active log categories. */ +std::vector ListActiveLogCategories(); /** Return true if str parses as a log category and set the flags in f */ bool GetLogCategory(uint64_t *f, const std::string *str); From b9e10fb42ee4a7449e752495e8c310f0f08c7610 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 10 Jun 2019 15:33:41 -0500 Subject: [PATCH 227/987] use new string method Signed-off-by: Pasta --- src/rpc/misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index cda3bb206033..f63b3f60c1a2 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -161,7 +161,7 @@ UniValue debug(const JSONRPCRequest& request) } } - return "Debug mode: " + ListActiveLogCategories(); + return "Debug mode: " + ListActiveLogCategoriesString(); } UniValue mnsync(const JSONRPCRequest& request) From 4b376794c0d5b82eff8e642527119b42b0960bc6 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 10 Jun 2019 15:36:50 -0500 Subject: [PATCH 228/987] use uint64 for flags Signed-off-by: Pasta --- src/rpc/misc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index f63b3f60c1a2..4423596baf57 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1194,7 +1194,7 @@ uint32_t getCategoryMask(UniValue cats) { cats = cats.get_array(); uint32_t mask = 0; for (unsigned int i = 0; i < cats.size(); ++i) { - uint32_t flag = 0; + uint64_t flag = 0; std::string cat = cats[i].get_str(); if (!GetLogCategory(&flag, &cat)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat); From 65d0fbf3c2f3ca7543c64fe96a6f9d36dda4a208 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 14 May 2017 12:43:33 +0200 Subject: [PATCH 229/987] Merge #10253: [test] Add test for getnetworkhashps de487b7 Tests: Add test for getnetworkhashps (Jimmy Song) Tree-SHA512: b1418ad904618f639ffa34dd40906692aff1fdf1a0d13a9af00039e7a6a2b758091734b89c0c91e8d455da6b15a0e435a9a9ca97a41d97bf395b844c761ffa27 --- test/functional/blockchain.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 487b9ec12400..014e7bc266a3 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -10,6 +10,7 @@ - getbestblockhash - getblockhash - getblockheader + - getnetworkhashps - verifychain Tests correspond to code in rpc/blockchain.cpp. @@ -39,6 +40,7 @@ def run_test(self): self._test_gettxoutsetinfo() self._test_getblockheader() self._test_getdifficulty() + self._test_getnetworkhashps() self.nodes[0].verifychain(4, 0) def _test_gettxoutsetinfo(self): @@ -110,5 +112,10 @@ def _test_getdifficulty(self): # binary => decimal => binary math is why we do this check assert abs(difficulty * 2**31 - 1) < 0.0001 + def _test_getnetworkhashps(self): + hashes_per_second = self.nodes[0].getnetworkhashps() + # This should be 2 hashes every 10 minutes or 1/300 + assert abs(hashes_per_second * 300 - 1) < 0.0001 + if __name__ == '__main__': BlockchainTest().main() From 823f858f4feb7242bde4700c02ad044b4e4da498 Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 07:55:08 -0500 Subject: [PATCH 230/987] apply concepts in 10198 to dash specific tests Signed-off-by: Pasta --- test/functional/dip3-deterministicmns.py | 2 -- test/functional/sporks.py | 7 +------ 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/test/functional/dip3-deterministicmns.py b/test/functional/dip3-deterministicmns.py index 037502379852..1cd6b225ba3f 100755 --- a/test/functional/dip3-deterministicmns.py +++ b/test/functional/dip3-deterministicmns.py @@ -26,10 +26,8 @@ def __init__(self): self.extra_args += ["-sporkkey=cP4EKFyJsHT39LDqgdcB43Y3YXjNyjb5Fuas1GQSeAtjnZWmZEQK"] self.extra_args += ["-dip3params=135:150"] - def setup_network(self): disable_mocktime() self.start_controller_node() - self.is_network_split = False def start_controller_node(self, extra_args=None): self.log.info("starting controller node") diff --git a/test/functional/sporks.py b/test/functional/sporks.py index 77d705cd0dff..d46b17ed9ce2 100755 --- a/test/functional/sporks.py +++ b/test/functional/sporks.py @@ -16,15 +16,10 @@ def __init__(self): super().__init__() self.num_nodes = 3 self.setup_clean_chain = True - self.is_network_split = False def setup_network(self): disable_mocktime() - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, - ["-sporkkey=cP4EKFyJsHT39LDqgdcB43Y3YXjNyjb5Fuas1GQSeAtjnZWmZEQK"])) - self.nodes.append(start_node(1, self.options.tmpdir)) - self.nodes.append(start_node(2, self.options.tmpdir)) + self.setup_nodes() # connect only 2 first nodes at start connect_nodes(self.nodes[0], 1) From d523ed81ee871b28a1fd2504afcc7c99cba175e9 Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 11:54:59 -0500 Subject: [PATCH 231/987] drop segwit 10318 Signed-off-by: Pasta --- test/functional/p2p-segwit.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 test/functional/p2p-segwit.py diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p-segwit.py deleted file mode 100755 index e69de29bb2d1..000000000000 From 5df0a96f7ede6b3a1a481aa21b571bbe7618a715 Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 12:25:09 -0500 Subject: [PATCH 232/987] adjust build_src.sh 10189 Signed-off-by: Pasta --- ci/build_src.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/build_src.sh b/ci/build_src.sh index 2a659e7efc8a..b3efc5cadcde 100755 --- a/ci/build_src.sh +++ b/ci/build_src.sh @@ -12,6 +12,8 @@ unset DISPLAY export CCACHE_COMPRESS=${CCACHE_COMPRESS:-1} export CCACHE_SIZE=${CCACHE_SIZE:-400M} +if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then contrib/devtools/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi + #if [ "$CHECK_DOC" = 1 ]; then contrib/devtools/check-doc.py; fi TODO reenable after all Bitcoin PRs have been merged and docs fully fixed depends/$HOST/native/bin/ccache --max-size=$CCACHE_SIZE From 577a4ce4b8c7817197e9ea3c67609991af805eab Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 13:01:12 -0500 Subject: [PATCH 233/987] use uint64_t Signed-off-by: Pasta --- src/rpc/misc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 4423596baf57..7ae798df0447 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1190,9 +1190,9 @@ UniValue getmemoryinfo(const JSONRPCRequest& request) } } -uint32_t getCategoryMask(UniValue cats) { +uint64_t getCategoryMask(UniValue cats) { cats = cats.get_array(); - uint32_t mask = 0; + uint64_t mask = 0; for (unsigned int i = 0; i < cats.size(); ++i) { uint64_t flag = 0; std::string cat = cats[i].get_str(); @@ -1224,7 +1224,7 @@ UniValue logging(const JSONRPCRequest& request) ); } - uint32_t originalLogCategories = logCategories; + uint64_t originalLogCategories = logCategories; if (request.params.size() > 0 && request.params[0].isArray()) { logCategories |= getCategoryMask(request.params[0]); } @@ -1238,7 +1238,7 @@ UniValue logging(const JSONRPCRequest& request) // in which case we should clear the BCLog::LIBEVENT flag. // Throw an error if the user has explicitly asked to change only the libevent // flag and it failed. - uint32_t changedLogCategories = originalLogCategories ^ logCategories; + uint64_t changedLogCategories = originalLogCategories ^ logCategories; if (changedLogCategories & BCLog::LIBEVENT) { if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) { logCategories &= ~BCLog::LIBEVENT; From 3b3132539fb256fa4d2689cab94bafdb40d71f6e Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 13:01:39 -0500 Subject: [PATCH 234/987] update python tests Signed-off-by: Pasta --- test/functional/mempool_persist.py | 4 ++-- test/functional/sporks.py | 1 + test/functional/test_framework/test_framework.py | 10 +++++----- test/functional/wallet-accounts.py | 2 +- test/functional/wallet-hd.py | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index 7b15476ea271..39dc2e2bff6a 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -67,7 +67,7 @@ def run_test(self): self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir)) self.nodes.append(start_node(1, self.options.tmpdir)) - # Give bitcoind a second to reload the mempool + # Give dashd a second to reload the mempool time.sleep(1) assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) assert_equal(len(self.nodes[1].getrawmempool()), 0) @@ -76,7 +76,7 @@ def run_test(self): stop_nodes(self.nodes) self.nodes = [] self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=0"])) - # Give bitcoind a second to reload the mempool + # Give dashd a second to reload the mempool time.sleep(1) assert_equal(len(self.nodes[0].getrawmempool()), 0) diff --git a/test/functional/sporks.py b/test/functional/sporks.py index d46b17ed9ce2..65783a4e8804 100755 --- a/test/functional/sporks.py +++ b/test/functional/sporks.py @@ -16,6 +16,7 @@ def __init__(self): super().__init__() self.num_nodes = 3 self.setup_clean_chain = True + self.extra_args = [["-sporkkey=cP4EKFyJsHT39LDqgdcB43Y3YXjNyjb5Fuas1GQSeAtjnZWmZEQK"], [], []] def setup_network(self): disable_mocktime() diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 0fe0cc93fb55..4767984af357 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -303,9 +303,10 @@ def _initialize_chain(self, test_dir, num_nodes, cachedir): shutil.rmtree(os.path.join(cachedir, "node" + str(i))) # Create cache directories, run dashds: + set_genesis_mocktime() for i in range(MAX_NODES): datadir = initialize_datadir(cachedir, i) - args = [os.getenv("DASHD", "dashd"), "-server", "-keypool=1", "-datadir=" + datadir, "-discover=0"] + args = [os.getenv("DASHD", "dashd"), "-server", "-keypool=1", "-datadir=" + datadir, "-discover=0", "-mocktime="+str(GENESISTIME)] if i > 0: args.append("-connect=127.0.0.1:" + str(p2p_port(0))) bitcoind_processes[i] = subprocess.Popen(args) @@ -328,14 +329,13 @@ def _initialize_chain(self, test_dir, num_nodes, cachedir): # # blocks are created with timestamps 10 minutes apart # starting from 2010 minutes in the past - enable_mocktime() - block_time = get_mocktime() - (201 * 10 * 60) + block_time = GENESISTIME for i in range(2): for peer in range(4): for j in range(25): set_node_times(self.nodes, block_time) self.nodes[peer].generate(1) - block_time += 10 * 60 + block_time += 156 # Must sync before next peer starts generating blocks sync_blocks(self.nodes) @@ -353,7 +353,7 @@ def _initialize_chain(self, test_dir, num_nodes, cachedir): from_dir = os.path.join(cachedir, "node" + str(i)) to_dir = os.path.join(test_dir, "node" + str(i)) shutil.copytree(from_dir, to_dir) - initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf + initialize_datadir(test_dir, i) # Overwrite port/rpcport in dsah.conf def _initialize_chain_clean(self, test_dir, num_nodes): """Initialize empty blockchain for use by the test. diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py index 50f852b2f20f..a0058bad4e90 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet-accounts.py @@ -54,7 +54,7 @@ def run_test(self): # send 500 from each address to a third address not in this wallet # There's some fee that will come back to us when the miner reward # matures. - common_address = "msf4WtN1YQKXvNtvdFYt9JBnUD2FB41kjr" + common_address = "yd5KMREs3GLMe6mTJYr3YrH1juwNwrFCfB" txid = node.sendmany( fromaccount="", amounts={common_address: 100}, diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index 6d0955e5606a..4b9cf6d3a708 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -82,7 +82,7 @@ def run_test (self): # Needs rescan self.stop_node(1) - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan']) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan'], redirect_stderr=True) #connect_nodes_bi(self.nodes, 0, 1) assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) From 867d3449a6a48e1a83aee84fd0fa74a26f794bd8 Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 13:05:39 -0500 Subject: [PATCH 235/987] adjust networkhashps test for dash block time Signed-off-by: Pasta --- test/functional/blockchain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 014e7bc266a3..ff6148c0c871 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -114,8 +114,8 @@ def _test_getdifficulty(self): def _test_getnetworkhashps(self): hashes_per_second = self.nodes[0].getnetworkhashps() - # This should be 2 hashes every 10 minutes or 1/300 - assert abs(hashes_per_second * 300 - 1) < 0.0001 + # This should be 2 hashes every 2.6 minutes (156 seconds) or 1/78 + assert abs(hashes_per_second * 78 - 1) < 0.0001 if __name__ == '__main__': BlockchainTest().main() From 3dcbb2e599dda3bc08751691992993ad8b6197b4 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 21 Jun 2019 16:44:29 +0300 Subject: [PATCH 236/987] fix bip68-112-113-p2p.py --- test/functional/bip68-112-113-p2p.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/functional/bip68-112-113-p2p.py b/test/functional/bip68-112-113-p2p.py index b0f045aa2a4f..dfa1dc3bd0f2 100755 --- a/test/functional/bip68-112-113-p2p.py +++ b/test/functional/bip68-112-113-p2p.py @@ -95,8 +95,14 @@ class BIP68_112_113Test(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 + # Must set the blockversion for this test + # Must also set '-maxtipage=600100' to allow syncing from very old blocks + # and '-dip3params=2000:2000' to create pre-dip3 blocks only self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-maxtipage=600100', '-dip3params=2000:2000']] + def setup_network(self): + self.setup_nodes() + def run_test(self): test = TestManager(self, self.options.tmpdir) test.add_all_connections(self.nodes) From badfdb451c67df0d533b10399e415776fc8c1499 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 20 Jun 2019 19:27:46 +0300 Subject: [PATCH 237/987] Fix rpc param names And corresponding locall variables too --- src/rpc/client.cpp | 18 +++++++++--------- src/wallet/rpcwallet.cpp | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 2350bae88e40..c5514b1ec57e 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -47,20 +47,20 @@ static const CRPCConvertParam vRPCConvertParams[] = { "instantsendtoaddress", 4, "comment_to" }, { "settxfee", 0, "amount" }, { "getreceivedbyaddress", 1, "minconf" }, - { "getreceivedbyaddress", 2, "addlockconf" }, + { "getreceivedbyaddress", 2, "addlocked" }, { "getreceivedbyaccount", 1, "minconf" }, - { "getreceivedbyaccount", 2, "addlockconf" }, + { "getreceivedbyaccount", 2, "addlocked" }, { "listaddressbalances", 0, "minamount" }, { "listreceivedbyaddress", 0, "minconf" }, - { "listreceivedbyaddress", 1, "addlockconf" }, + { "listreceivedbyaddress", 1, "addlocked" }, { "listreceivedbyaddress", 2, "include_empty" }, { "listreceivedbyaddress", 3, "include_watchonly" }, { "listreceivedbyaccount", 0, "minconf" }, - { "listreceivedbyaccount", 1, "addlockconf" }, + { "listreceivedbyaccount", 1, "addlocked" }, { "listreceivedbyaccount", 2, "include_empty" }, { "listreceivedbyaccount", 3, "include_watchonly" }, { "getbalance", 1, "minconf" }, - { "getbalance", 2, "addlockconf" }, + { "getbalance", 2, "addlocked" }, { "getbalance", 3, "include_watchonly" }, { "getchaintips", 0, "count" }, { "getchaintips", 1, "branchlen" }, @@ -74,12 +74,12 @@ static const CRPCConvertParam vRPCConvertParams[] = { "move", 3, "minconf" }, { "sendfrom", 2, "amount" }, { "sendfrom", 3, "minconf" }, - { "sendfrom", 4, "addlockconf" }, + { "sendfrom", 4, "addlocked" }, { "listtransactions", 1, "count" }, { "listtransactions", 2, "skip" }, { "listtransactions", 3, "include_watchonly" }, { "listaccounts", 0, "minconf" }, - { "listaccounts", 1, "addlockconf" }, + { "listaccounts", 1, "addlocked" }, { "listaccounts", 2, "include_watchonly" }, { "walletpassphrase", 1, "timeout" }, { "walletpassphrase", 2, "mixingonly" }, @@ -88,8 +88,8 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listsinceblock", 2, "include_watchonly" }, { "sendmany", 1, "amounts" }, { "sendmany", 2, "minconf" }, - { "sendmany", 3, "addlockconf" }, - { "sendmany", 5, "subtractfeefromamount" }, + { "sendmany", 3, "addlocked" }, + { "sendmany", 5, "subtractfeefrom" }, { "sendmany", 6, "use_is" }, { "sendmany", 7, "use_ps" }, { "addmultisigaddress", 0, "nrequired" }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7ace6b8ce9bb..0ebcb0f246f8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1031,7 +1031,7 @@ UniValue sendmany(const JSONRPCRequest& request) if (request.fHelp || request.params.size() < 2 || request.params.size() > 8) throw std::runtime_error( - "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf addlocked \"comment\" [\"address\",...] subtractfeefromamount use_is use_ps )\n" + "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf addlocked \"comment\" [\"address\",...] subtractfeefrom use_is use_ps )\n" "\nSend multiple times. Amounts are double-precision floating point numbers." + HelpRequiringPassphrase(pwallet) + "\n" "\nArguments:\n" @@ -1044,7 +1044,7 @@ UniValue sendmany(const JSONRPCRequest& request) "3. minconf (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n" "4. addlocked (bool, optional, default=false) Whether to include transactions locked via InstantSend.\n" "5. \"comment\" (string, optional) A comment\n" - "6. subtractfeefromamount (array, optional) A json array with addresses.\n" + "6. subtractfeefrom (array, optional) A json array with addresses.\n" " The fee will be equally deducted from the amount of each selected address.\n" " Those recipients will receive less dashs than you enter in their corresponding amount field.\n" " If no addresses are specified here, the sender pays the fee.\n" @@ -1084,9 +1084,9 @@ UniValue sendmany(const JSONRPCRequest& request) if (request.params.size() > 4 && !request.params[4].isNull() && !request.params[4].get_str().empty()) wtx.mapValue["comment"] = request.params[4].get_str(); - UniValue subtractFeeFromAmount(UniValue::VARR); + UniValue subtractFeeFrom(UniValue::VARR); if (request.params.size() > 5) - subtractFeeFromAmount = request.params[5].get_array(); + subtractFeeFrom = request.params[5].get_array(); std::set setAddress; std::vector vecSend; @@ -1110,8 +1110,8 @@ UniValue sendmany(const JSONRPCRequest& request) totalAmount += nAmount; bool fSubtractFeeFromAmount = false; - for (unsigned int idx = 0; idx < subtractFeeFromAmount.size(); idx++) { - const UniValue& addr = subtractFeeFromAmount[idx]; + for (unsigned int idx = 0; idx < subtractFeeFrom.size(); idx++) { + const UniValue& addr = subtractFeeFrom[idx]; if (addr.get_str() == name_) fSubtractFeeFromAmount = true; } From 23114cdb2094209da99483d61afbb90e4fc3a37d Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 20 Jun 2019 19:36:17 +0300 Subject: [PATCH 238/987] Drop redirect_stderr and pass stderr instead --- test/functional/dip3-deterministicmns.py | 2 +- test/functional/fundrawtransaction-hd.py | 4 ++-- test/functional/keypool-hd.py | 4 ++-- test/functional/pruning.py | 10 +++++----- test/functional/test_framework/test_framework.py | 14 ++++++++------ test/functional/test_framework/util.py | 11 +++-------- test/functional/wallet-dump.py | 4 ++-- test/functional/wallet-hd.py | 9 ++++++--- test/functional/wallet.py | 4 ++-- 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/test/functional/dip3-deterministicmns.py b/test/functional/dip3-deterministicmns.py index 1cd6b225ba3f..9e1934f122d0 100755 --- a/test/functional/dip3-deterministicmns.py +++ b/test/functional/dip3-deterministicmns.py @@ -250,7 +250,7 @@ def start_mn(self, mn): while len(self.nodes) <= mn.idx: self.nodes.append(None) extra_args = ['-masternode=1', '-masternodeblsprivkey=%s' % mn.blsMnkey] - n = start_node(mn.idx, self.options.tmpdir, self.extra_args + extra_args, redirect_stderr=True) + n = start_node(mn.idx, self.options.tmpdir, self.extra_args + extra_args, stderr=sys.stdout) self.nodes[mn.idx] = n for i in range(0, self.num_nodes): if i < len(self.nodes) and self.nodes[i] is not None and i != mn.idx: diff --git a/test/functional/fundrawtransaction-hd.py b/test/functional/fundrawtransaction-hd.py index 6e0c7645a60e..27aeb751815a 100755 --- a/test/functional/fundrawtransaction-hd.py +++ b/test/functional/fundrawtransaction-hd.py @@ -15,7 +15,7 @@ def __init__(self): self.num_nodes = 4 def setup_network(self, split=False): - self.nodes = start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, redirect_stderr=True) + self.nodes = start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, stderr=sys.stdout) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) @@ -446,7 +446,7 @@ def run_test(self): stop_node(self.nodes[1], 2) stop_node(self.nodes[2], 3) - self.nodes = start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, redirect_stderr=True) + self.nodes = start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, stderr=sys.stdout) # This test is not meant to test fee estimation and we'd like # to be sure all txs are sent at a consistent desired feerate for node in self.nodes: diff --git a/test/functional/keypool-hd.py b/test/functional/keypool-hd.py index 93a0935c1e74..51604cd4ea34 100755 --- a/test/functional/keypool-hd.py +++ b/test/functional/keypool-hd.py @@ -28,7 +28,7 @@ def run_test(self): nodes[0].encryptwallet('test') bitcoind_processes[0].wait() # Restart node 0 - nodes[0] = start_node(0, self.options.tmpdir, ['-usehd=1'], redirect_stderr=True) + nodes[0] = start_node(0, self.options.tmpdir, ['-usehd=1'], stderr=sys.stdout) # Keep creating keys addr = nodes[0].getnewaddress() addr_data = nodes[0].validateaddress(addr) @@ -104,7 +104,7 @@ def run_test(self): assert_equal(wi['keypoolsize'], 100) def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, [['-usehd=1']], redirect_stderr=True) + self.nodes = start_nodes(1, self.options.tmpdir, [['-usehd=1']], stderr=sys.stdout) if __name__ == '__main__': KeyPoolTest().main() diff --git a/test/functional/pruning.py b/test/functional/pruning.py index 63dfeb59132e..18e79670957e 100755 --- a/test/functional/pruning.py +++ b/test/functional/pruning.py @@ -218,13 +218,13 @@ def reorg_back(self): def manual_test(self, node_number, use_timestamp): # at this point, node has 995 blocks and has not yet run in prune mode - node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0"], redirect_stderr=True, timewait=900) + node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0"], stderr=sys.stdout, timewait=900) assert_equal(node.getblockcount(), 995) assert_raises_jsonrpc(-1, "not in prune mode", node.pruneblockchain, 500) self.stop_node(node_number) # now re-start in manual pruning mode - node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=1"], redirect_stderr=True, timewait=900) + node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=1"], stderr=sys.stdout, timewait=900) assert_equal(node.getblockcount(), 995) def height(index): @@ -298,7 +298,7 @@ def has_block(index): # stop node, start back up with auto-prune at 550MB, make sure still runs self.stop_node(node_number) - self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], redirect_stderr=True, timewait=900) + self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout, timewait=900) self.log.info("Success") @@ -306,7 +306,7 @@ def wallet_test(self): # check that the pruning node's wallet is still in good shape self.log.info("Stop and start pruning node to trigger wallet rescan") self.stop_node(2) - start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], redirect_stderr=True) + start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) self.log.info("Success") # check that wallet loads loads successfully when restarting a pruned node after IBD. @@ -316,7 +316,7 @@ def wallet_test(self): nds = [self.nodes[0], self.nodes[5]] sync_blocks(nds, wait=5, timeout=300) self.stop_node(5) #stop and start to trigger rescan - start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], redirect_stderr=True) + start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) self.log.info("Success") def run_test(self): diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 4767984af357..f0ac4783a9f8 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -103,11 +103,11 @@ def setup_network(self): connect_nodes_bi(self.nodes, i, i + 1) self.sync_all() - def setup_nodes(self): + def setup_nodes(self, stderr=None): extra_args = None if hasattr(self, "extra_args"): extra_args = self.extra_args - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args, stderr=stderr) def run_test(self): raise NotImplementedError @@ -219,8 +219,8 @@ def main(self): def start_node(self, i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): return start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr) - def start_nodes(self, num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None): - return start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary) + def start_nodes(self, num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): + return start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary, stderr) def stop_node(self, num_node): stop_node(self.nodes[num_node], num_node) @@ -281,7 +281,7 @@ def _start_logging(self): rpc_handler.setLevel(logging.DEBUG) rpc_logger.addHandler(rpc_handler) - def _initialize_chain(self, test_dir, num_nodes, cachedir): + def _initialize_chain(self, test_dir, num_nodes, cachedir, extra_args=None, stderr=None): """Initialize a pre-mined blockchain for use by the test. Create a cache of a 200-block-long chain (with wallet) for MAX_NODES @@ -309,7 +309,9 @@ def _initialize_chain(self, test_dir, num_nodes, cachedir): args = [os.getenv("DASHD", "dashd"), "-server", "-keypool=1", "-datadir=" + datadir, "-discover=0", "-mocktime="+str(GENESISTIME)] if i > 0: args.append("-connect=127.0.0.1:" + str(p2p_port(0))) - bitcoind_processes[i] = subprocess.Popen(args) + if extra_args is not None: + args.extend(extra_args) + bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr) self.log.debug("initialize_chain: dashd started, waiting for RPC to come up") wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) self.log.debug("initialize_chain: RPC successfully started") diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 343a871ff546..247d702bb5ec 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -251,7 +251,7 @@ def wait_for_bitcoind_start(process, url, i): time.sleep(0.25) -def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, redirect_stderr=False, stderr=None): +def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): """ Start a dashd and return RPC connection to it """ @@ -264,11 +264,6 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= args += [ "-createwalletbackups=0" ] if extra_args is not None: args.extend(extra_args) - # Allow to redirect stderr to stdout in case we expect some non-critical warnings/errors printed to stderr - # Otherwise the whole test would be considered to be failed in such cases - if redirect_stderr: - stderr = sys.stdout - bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr) logger.debug("initialize_chain: dashd started, waiting for RPC to come up") url = rpc_url(i, rpchost) @@ -300,7 +295,7 @@ def assert_start_raises_init_error(i, dirname, extra_args=None, expected_msg=Non assert_msg = "dashd should have exited with expected error " + expected_msg raise AssertionError(assert_msg) -def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, redirect_stderr=False): +def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): """ Start multiple dashds, return RPC connections to them """ @@ -311,7 +306,7 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None rpcs = [] try: for i in range(num_nodes): - rpcs.append(start_node(i, dirname, extra_args[i], rpchost, timewait=timewait, binary=binary[i], redirect_stderr=redirect_stderr)) + rpcs.append(start_node(i, dirname, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=stderr)) except: # If one node failed to start, stop the others stop_nodes(rpcs) raise diff --git a/test/functional/wallet-dump.py b/test/functional/wallet-dump.py index f6aa42a3abe0..881657a6d127 100755 --- a/test/functional/wallet-dump.py +++ b/test/functional/wallet-dump.py @@ -64,7 +64,7 @@ def __init__(self): def setup_chain(self): # TODO remove this when usehd=1 becomes the default # use our own cache and -usehd=1 as extra arg as the default cache is run with -usehd=0 - initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir + "/hd", ["-usehd=1"], redirect_stderr=True) + self._initialize_chain(os.path.join(self.options.tmpdir, "hd"), self.num_nodes, os.path.join(self.options.cachedir, "hd"), extra_args=self.extra_args[0], stderr=sys.stdout) set_cache_mocktime() def setup_network(self, split=False): @@ -72,7 +72,7 @@ def setup_network(self, split=False): # longer than the default 30 seconds due to an expensive # CWallet::TopUpKeyPool call, and the encryptwallet RPC made later in # the test often takes even longer. - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args, timewait=60, redirect_stderr=True) + self.nodes = start_nodes(self.num_nodes, os.path.join(self.options.tmpdir, "hd"), self.extra_args, timewait=60, stderr=sys.stdout) def run_test (self): tmpdir = self.options.tmpdir diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index 4b9cf6d3a708..022cfb19fc2b 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -15,13 +15,16 @@ def __init__(self): self.num_nodes = 2 self.extra_args = [['-usehd=0'], ['-usehd=1', '-keypool=0']] + def setup_network(self): + self.setup_nodes(stderr=sys.stdout) + def run_test (self): tmpdir = self.options.tmpdir # Make sure can't switch off usehd after wallet creation self.stop_node(1) assert_start_raises_init_error(1, self.options.tmpdir, ['-usehd=0'], 'already existing HD wallet') - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1], redirect_stderr=True) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1], stderr=sys.stdout) connect_nodes_bi(self.nodes, 0, 1) # Make sure we use hd, keep chainid @@ -68,7 +71,7 @@ def run_test (self): stop_node(self.nodes[1],1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1], redirect_stderr=True) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1], stderr=sys.stdout) #connect_nodes_bi(self.nodes, 0, 1) # Assert that derivation is deterministic @@ -82,7 +85,7 @@ def run_test (self): # Needs rescan self.stop_node(1) - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan'], redirect_stderr=True) + self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan'], stderr=sys.stdout) #connect_nodes_bi(self.nodes, 0, 1) assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) diff --git a/test/functional/wallet.py b/test/functional/wallet.py index 8ad41a58e42b..70ed64390f15 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -21,7 +21,7 @@ def __init__(self): self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)] def setup_network(self): - self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3], redirect_stderr=True) + self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3], stderr=sys.stdout) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -178,7 +178,7 @@ def run_test(self): txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) sync_mempools(self.nodes) - self.nodes.append(start_node(3, self.options.tmpdir, self.extra_args[3], redirect_stderr=True)) + self.nodes.append(start_node(3, self.options.tmpdir, self.extra_args[3], stderr=sys.stdout)) connect_nodes_bi(self.nodes, 0, 3) sync_blocks(self.nodes) From f02bf18eecf401fd286cc9ca8f5b59cd188857eb Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 20 Jun 2019 19:37:09 +0300 Subject: [PATCH 239/987] Other fixes --- test/functional/dip3-deterministicmns.py | 2 ++ test/functional/fundrawtransaction-hd.py | 10 +++------- test/functional/fundrawtransaction.py | 3 ++- test/functional/listtransactions.py | 2 +- test/functional/p2p-compactblocks.py | 2 +- test/functional/p2p-fingerprint.py | 5 ----- test/functional/prioritise_transaction.py | 2 +- test/functional/receivedby.py | 2 +- .../test_framework/test_framework.py | 20 ++++++++----------- test/functional/wallet-accounts.py | 10 ++++++---- test/functional/wallet-dump.py | 10 ++++------ 11 files changed, 29 insertions(+), 39 deletions(-) diff --git a/test/functional/dip3-deterministicmns.py b/test/functional/dip3-deterministicmns.py index 9e1934f122d0..65421ce54ed1 100755 --- a/test/functional/dip3-deterministicmns.py +++ b/test/functional/dip3-deterministicmns.py @@ -26,6 +26,8 @@ def __init__(self): self.extra_args += ["-sporkkey=cP4EKFyJsHT39LDqgdcB43Y3YXjNyjb5Fuas1GQSeAtjnZWmZEQK"] self.extra_args += ["-dip3params=135:150"] + + def setup_network(self): disable_mocktime() self.start_controller_node() diff --git a/test/functional/fundrawtransaction-hd.py b/test/functional/fundrawtransaction-hd.py index 27aeb751815a..e9500c6d6cd7 100755 --- a/test/functional/fundrawtransaction-hd.py +++ b/test/functional/fundrawtransaction-hd.py @@ -13,18 +13,15 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 4 + self.extra_args = [['-usehd=1']] * self.num_nodes - def setup_network(self, split=False): - self.nodes = start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, stderr=sys.stdout) - + def setup_network(self): + self.setup_nodes(stderr=sys.stdout) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) connect_nodes_bi(self.nodes,0,3) - self.is_network_split=False - self.sync_all() - def run_test(self): self.log.info("Mining blocks...") @@ -456,7 +453,6 @@ def run_test(self): connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) connect_nodes_bi(self.nodes,0,3) - self.is_network_split=False self.sync_all() # drain the keypool diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index 649c33d43195..14fc51fca20a 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -21,9 +21,10 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 4 + self.extra_args = [['-usehd=0']] * self.num_nodes def setup_network(self, split=False): - self.setup_nodes([['-usehd=0']] * self.num_nodes) + self.setup_nodes() connect_nodes_bi(self.nodes, 0, 1) connect_nodes_bi(self.nodes, 1, 2) diff --git a/test/functional/listtransactions.py b/test/functional/listtransactions.py index c4a466b8af4b..4642c213bd27 100755 --- a/test/functional/listtransactions.py +++ b/test/functional/listtransactions.py @@ -23,7 +23,7 @@ def __init__(self): def setup_nodes(self): #This test requires mocktime - enable_mocktime() + set_cache_mocktime() self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p-compactblocks.py index f44db3538ebd..a1377aeb67f8 100755 --- a/test/functional/p2p-compactblocks.py +++ b/test/functional/p2p-compactblocks.py @@ -95,7 +95,7 @@ def __init__(self): self.setup_clean_chain = True # both nodes has the same version self.num_nodes = 2 - self.extra_args = [["-txindex"]] + self.extra_args = [["-txindex"]] * 2 self.utxos = [] def build_block_on_tip(self, node): diff --git a/test/functional/p2p-fingerprint.py b/test/functional/p2p-fingerprint.py index 617c6c150c67..aae51ea5d352 100755 --- a/test/functional/p2p-fingerprint.py +++ b/test/functional/p2p-fingerprint.py @@ -40,11 +40,6 @@ def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 - # TODO also remove this when bitcoin#11121 is backported - def setup_network(self, split=False): - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) - self.is_network_split = False - # Build a chain of blocks on top of given one def build_chain(self, nblocks, prev_hash, prev_height, prev_median_time): blocks = [] diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py index 4258d201243c..e72abc01c25a 100755 --- a/test/functional/prioritise_transaction.py +++ b/test/functional/prioritise_transaction.py @@ -14,7 +14,7 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 2 - self.extra_args = [["-printpriority=1"] * 2] + self.extra_args = [["-printpriority=1"]] * 2 def run_test(self): self.txouts = gen_return_txouts() diff --git a/test/functional/receivedby.py b/test/functional/receivedby.py index b0d94741573a..9912f7b9ea72 100755 --- a/test/functional/receivedby.py +++ b/test/functional/receivedby.py @@ -31,7 +31,7 @@ def __init__(self): def setup_nodes(self): #This test requires mocktime - enable_mocktime() + set_cache_mocktime() self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index f0ac4783a9f8..8ab9afb99644 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -17,25 +17,29 @@ from concurrent.futures import ThreadPoolExecutor from .util import ( - assert_equal, - start_nodes, PortSeed, + GENESISTIME, MAX_NODES, + assert_equal, bitcoind_processes, check_json_precision, connect_nodes_bi, connect_nodes, + copy_datadir, disable_mocktime, disconnect_nodes, enable_coverage, - enable_mocktime, get_mocktime, get_rpc_proxy, initialize_datadir, log_filename, p2p_port, rpc_url, + set_cache_mocktime, + set_genesis_mocktime, + set_mocktime, set_node_times, + satoshi_round, start_node, start_nodes, stop_node, @@ -44,15 +48,7 @@ sync_mempools, sync_masternodes, wait_for_bitcoind_start, - set_cache_mocktime, - set_genesis_mocktime, - get_mocktime, - set_mocktime, - set_node_times, - p2p_port, - satoshi_round, - wait_to_sync, - copy_datadir) + wait_to_sync) from .authproxy import JSONRPCException class BitcoinTestFramework(object): diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py index a0058bad4e90..816d7009faef 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet-accounts.py @@ -25,7 +25,7 @@ def __init__(self): super().__init__() self.setup_clean_chain = True self.num_nodes = 1 - self.extra_args = [[]] + self.extra_args = [["-paytxfee=0.0001"]] def run_test(self): node = self.nodes[0] @@ -33,7 +33,7 @@ def run_test(self): assert_equal(len(node.listunspent()), 0) # Note each time we call generate, all generated coins go into - # the same address, so we call twice to get two addresses w/50 each + # the same address, so we call twice to get two addresses w/500 each node.generate(1) node.generate(101) assert_equal(node.getbalance(), 1000) @@ -57,9 +57,11 @@ def run_test(self): common_address = "yd5KMREs3GLMe6mTJYr3YrH1juwNwrFCfB" txid = node.sendmany( fromaccount="", - amounts={common_address: 100}, - subtractfeefrom=[common_address], + amounts={common_address: 1000}, minconf=1, + addlocked=False, + comment="", + subtractfeefrom=[common_address], ) tx_details = node.gettransaction(txid) fee = -tx_details['details'][0]['fee'] diff --git a/test/functional/wallet-dump.py b/test/functional/wallet-dump.py index 881657a6d127..67e4f3f71201 100755 --- a/test/functional/wallet-dump.py +++ b/test/functional/wallet-dump.py @@ -57,17 +57,15 @@ class WalletDumpTest(BitcoinTestFramework): def __init__(self): super().__init__() - self.setup_clean_chain = False + self.setup_clean_chain = True self.num_nodes = 1 self.extra_args = [["-keypool=90", "-usehd=1"]] - def setup_chain(self): + def setup_network(self): # TODO remove this when usehd=1 becomes the default # use our own cache and -usehd=1 as extra arg as the default cache is run with -usehd=0 self._initialize_chain(os.path.join(self.options.tmpdir, "hd"), self.num_nodes, os.path.join(self.options.cachedir, "hd"), extra_args=self.extra_args[0], stderr=sys.stdout) set_cache_mocktime() - - def setup_network(self, split=False): # Use 1 minute timeout because the initial getnewaddress RPC can take # longer than the default 30 seconds due to an expensive # CWallet::TopUpKeyPool call, and the encryptwallet RPC made later in @@ -75,7 +73,7 @@ def setup_network(self, split=False): self.nodes = start_nodes(self.num_nodes, os.path.join(self.options.tmpdir, "hd"), self.extra_args, timewait=60, stderr=sys.stdout) def run_test (self): - tmpdir = self.options.tmpdir + tmpdir = os.path.join(self.options.tmpdir, "hd") # generate 20 addresses to compare against the dump test_addr_count = 20 @@ -99,7 +97,7 @@ def run_test (self): #encrypt wallet, restart, unlock and dump self.nodes[0].encryptwallet('test') bitcoind_processes[0].wait() - self.nodes[0] = start_node(0, self.options.tmpdir, self.extra_args[0]) + self.nodes[0] = start_node(0, tmpdir, self.extra_args[0]) self.nodes[0].walletpassphrase('test', 10) # Should be a no-op: self.nodes[0].keypoolrefill() From 1f6e0435b4d446babafdc36038d085694f3fe2d0 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Fri, 21 Jun 2019 19:24:32 -0500 Subject: [PATCH 240/987] [Trivial] Fix a typo in a comment in mnauth.h (#2988) Signed-off-by: Pasta --- src/evo/mnauth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/mnauth.h b/src/evo/mnauth.h index f0e7a174bc85..530122a3ca76 100644 --- a/src/evo/mnauth.h +++ b/src/evo/mnauth.h @@ -29,7 +29,7 @@ class UniValue; * This is fine as we only use this mechanism for DoS protection. It allows us to keep masternode connections open for * a very long time without evicting the connections when inbound connection limits are hit (non-MNs will then be evicted). * - * If we ever want to add transfer of sensible data, THIS AUTHENTICATION MECHANISM IS NOT ENOUGH!! We'd need to implement + * If we ever want to add transfer of sensitive data, THIS AUTHENTICATION MECHANISM IS NOT ENOUGH!! We'd need to implement * proper encryption for these connections first. */ From a1770b0c25f5f667b87ccd0f039c88b628527721 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 21 Mar 2016 12:54:28 +0100 Subject: [PATCH 241/987] Merge #7692: Remove p2p alert system cfd519e Add release note documentation (BtcDrak) 6601ce5 protocol.h/cpp: Removes NetMsgType::ALERT (Thomas Kerin) ad72104 Formatting (BtcDrak) 1b77471 Remove alert keys (BtcDrak) 01fdfef Remove `-alerts` option (BtcDrak) 9206634 Update alert notification and GUI (BtcDrak) bbb9d1d Remove p2p alert handling (BtcDrak) manual fixes Signed-off-by: Pasta remove sendalert.cpp Signed-off-by: Pasta CAlertNotify -> AlertNotify Signed-off-by: Pasta remove alert.h Signed-off-by: Pasta remove vAlertPubKey for DevNet Signed-off-by: Pasta remove src/main.cpp --- src/Makefile.am | 3 - src/Makefile.test.include | 2 +- src/alert.cpp | 286 ----------------------------------- src/alert.h | 114 -------------- src/chainparams.cpp | 3 - src/chainparams.h | 3 - src/init.cpp | 3 - src/net_processing.cpp | 39 ----- src/protocol.cpp | 2 - src/protocol.h | 7 - src/qt/clientmodel.cpp | 27 +--- src/qt/clientmodel.h | 4 +- src/sendalert.cpp | 112 -------------- src/test/alert_tests.cpp | 265 +++++++------------------------- src/test/data/alertTests.raw | Bin 1280 -> 0 bytes src/ui_interface.h | 5 +- src/validation.cpp | 28 +++- src/validation.h | 3 - src/warnings.cpp | 19 --- 19 files changed, 89 insertions(+), 836 deletions(-) delete mode 100644 src/alert.cpp delete mode 100644 src/alert.h delete mode 100644 src/sendalert.cpp delete mode 100644 src/test/data/alertTests.raw diff --git a/src/Makefile.am b/src/Makefile.am index e3a08b6125fc..c3b2d83067b5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -105,7 +105,6 @@ BITCOIN_CORE_H = \ addressindex.h \ spentindex.h \ addrman.h \ - alert.h \ base58.h \ batchedlogger.h \ bip39.h \ @@ -262,7 +261,6 @@ libdash_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libdash_server_a_SOURCES = \ addrdb.cpp \ addrman.cpp \ - alert.cpp \ batchedlogger.cpp \ bloom.cpp \ blockencodings.cpp \ @@ -330,7 +328,6 @@ libdash_server_a_SOURCES = \ rpc/server.cpp \ script/sigcache.cpp \ script/ismine.cpp \ - sendalert.cpp \ spork.cpp \ timedata.cpp \ torcontrol.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index e3dcb433ac14..bd9ef26db6d9 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -20,7 +20,7 @@ JSON_TEST_FILES = \ test/data/tx_valid.json \ test/data/sighash.json -RAW_TEST_FILES = test/data/alertTests.raw +RAW_TEST_FILES = GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h) diff --git a/src/alert.cpp b/src/alert.cpp deleted file mode 100644 index 59c8b10b03f5..000000000000 --- a/src/alert.cpp +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "alert.h" - -#include "base58.h" -#include "clientversion.h" -#include "net.h" -#include "netmessagemaker.h" -#include "pubkey.h" -#include "timedata.h" -#include "ui_interface.h" -#include "util.h" -#include "utilstrencodings.h" - -#include -#include -#include - -#include -#include -#include - -std::map mapAlerts; -CCriticalSection cs_mapAlerts; - -void CUnsignedAlert::SetNull() -{ - nVersion = 1; - nRelayUntil = 0; - nExpiration = 0; - nID = 0; - nCancel = 0; - setCancel.clear(); - nMinVer = 0; - nMaxVer = 0; - setSubVer.clear(); - nPriority = 0; - - strComment.clear(); - strStatusBar.clear(); - strReserved.clear(); -} - -std::string CUnsignedAlert::ToString() const -{ - std::string strSetCancel; - for (const auto& n : setCancel) - strSetCancel += strprintf("%d ", n); - std::string strSetSubVer; - for (const auto& str : setSubVer) - strSetSubVer += "\"" + str + "\" "; - return strprintf( - "CAlert(\n" - " nVersion = %d\n" - " nRelayUntil = %d\n" - " nExpiration = %d\n" - " nID = %d\n" - " nCancel = %d\n" - " setCancel = %s\n" - " nMinVer = %d\n" - " nMaxVer = %d\n" - " setSubVer = %s\n" - " nPriority = %d\n" - " strComment = \"%s\"\n" - " strStatusBar = \"%s\"\n" - ")\n", - nVersion, - nRelayUntil, - nExpiration, - nID, - nCancel, - strSetCancel, - nMinVer, - nMaxVer, - strSetSubVer, - nPriority, - strComment, - strStatusBar); -} - -void CAlert::SetNull() -{ - CUnsignedAlert::SetNull(); - vchMsg.clear(); - vchSig.clear(); -} - -bool CAlert::IsNull() const -{ - return (nExpiration == 0); -} - -uint256 CAlert::GetHash() const -{ - return Hash(this->vchMsg.begin(), this->vchMsg.end()); -} - -bool CAlert::IsInEffect() const -{ - return (GetAdjustedTime() < nExpiration); -} - -bool CAlert::Cancels(const CAlert& alert) const -{ - if (!IsInEffect()) - return false; // this was a no-op before 31403 - return (alert.nID <= nCancel || setCancel.count(alert.nID)); -} - -bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const -{ - // TODO: rework for client-version-embedded-in-strSubVer ? - return (IsInEffect() && - nMinVer <= nVersion && nVersion <= nMaxVer && - (setSubVer.empty() || setSubVer.count(strSubVerIn))); -} - -bool CAlert::AppliesToMe() const -{ - return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector())); -} - -bool CAlert::RelayTo(CNode* pnode, CConnman& connman) const -{ - if (!IsInEffect()) - return false; - // don't relay to nodes which haven't sent their version message - if (pnode->nVersion == 0) - return false; - // returns true if wasn't already contained in the set - if (pnode->setKnown.insert(GetHash()).second) - { - if (AppliesTo(pnode->nVersion, pnode->strSubVer) || - AppliesToMe() || - GetAdjustedTime() < nRelayUntil) - { - connman.PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::ALERT, *this)); - return true; - } - } - return false; -} - -bool CAlert::Sign() -{ - CDataStream sMsg(SER_NETWORK, CLIENT_VERSION); - sMsg << *(CUnsignedAlert*)this; - vchMsg = std::vector(sMsg.begin(), sMsg.end()); - CBitcoinSecret vchSecret; - if (!vchSecret.SetString(GetArg("-alertkey", ""))) - { - printf("CAlert::SignAlert() : vchSecret.SetString failed\n"); - return false; - } - CKey key = vchSecret.GetKey(); - if (!key.Sign(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) - { - printf("CAlert::SignAlert() : key.Sign failed\n"); - return false; - } - - return true; -} - -bool CAlert::CheckSignature(const std::vector& alertKey) const -{ - CPubKey key(alertKey); - if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) - return error("CAlert::CheckSignature(): verify signature failed"); - - // Now unserialize the data - CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION); - sMsg >> *(CUnsignedAlert*)this; - return true; -} - -CAlert CAlert::getAlertByHash(const uint256 &hash) -{ - CAlert retval; - { - LOCK(cs_mapAlerts); - std::map::iterator mi = mapAlerts.find(hash); - if(mi != mapAlerts.end()) - retval = mi->second; - } - return retval; -} - -bool CAlert::ProcessAlert(const std::vector& alertKey, bool fThread) const -{ - if (!CheckSignature(alertKey)) - return false; - if (!IsInEffect()) - return false; - - // alert.nID=max is reserved for if the alert key is - // compromised. It must have a pre-defined message, - // must never expire, must apply to all versions, - // and must cancel all previous - // alerts or it will be ignored (so an attacker can't - // send an "everything is OK, don't panic" version that - // cannot be overridden): - int maxInt = std::numeric_limits::max(); - if (nID == maxInt) - { - if (!( - nExpiration == maxInt && - nCancel == (maxInt-1) && - nMinVer == 0 && - nMaxVer == maxInt && - setSubVer.empty() && - nPriority == maxInt && - strStatusBar == "URGENT: Alert key compromised, upgrade required" - )) - return false; - } - - { - LOCK(cs_mapAlerts); - // Cancel previous alerts - for (std::map::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();) - { - const CAlert& alert = (*mi).second; - if (Cancels(alert)) - { - LogPrint(BCLog::ALERT, "cancelling alert %d\n", alert.nID); - uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); - mapAlerts.erase(mi++); - } - else if (!alert.IsInEffect()) - { - LogPrint(BCLog::ALERT, "expiring alert %d\n", alert.nID); - uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); - mapAlerts.erase(mi++); - } - else - mi++; - } - - // Check if this alert has been cancelled - for (const auto& item : mapAlerts) - { - const CAlert& alert = item.second; - if (alert.Cancels(*this)) - { - LogPrint(BCLog::ALERT, "alert already cancelled by %d\n", alert.nID); - return false; - } - } - - // Add to mapAlerts - mapAlerts.insert(std::make_pair(GetHash(), *this)); - // Notify UI and -alertnotify if it applies to me - if(AppliesToMe()) - { - uiInterface.NotifyAlertChanged(GetHash(), CT_NEW); - Notify(strStatusBar, fThread); - } - } - - LogPrint(BCLog::ALERT, "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); - return true; -} - -void -CAlert::Notify(const std::string& strMessage, bool fThread) -{ - std::string strCmd = GetArg("-alertnotify", ""); - if (strCmd.empty()) return; - - // Alert text should be plain ascii coming from a trusted source, but to - // be safe we first strip anything not in safeChars, then add single quotes around - // the whole string before passing it to the shell: - std::string singleQuote("'"); - std::string safeStatus = SanitizeString(strMessage); - safeStatus = singleQuote+safeStatus+singleQuote; - boost::replace_all(strCmd, "%s", safeStatus); - - if (fThread) - boost::thread t(runCommand, strCmd); // thread runs free - else - runCommand(strCmd); -} diff --git a/src/alert.h b/src/alert.h deleted file mode 100644 index edd4d862de11..000000000000 --- a/src/alert.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_ALERT_H -#define BITCOIN_ALERT_H - -#include "serialize.h" -#include "sync.h" - -#include -#include -#include -#include - -class CAlert; -class CNode; -class CConnman; -class uint256; - -extern std::map mapAlerts; -extern CCriticalSection cs_mapAlerts; - -/** Alerts are for notifying old versions if they become too obsolete and - * need to upgrade. The message is displayed in the status bar. - * Alert messages are broadcast as a vector of signed data. Unserializing may - * not read the entire buffer if the alert is for a newer version, but older - * versions can still relay the original data. - */ -class CUnsignedAlert -{ -public: - int nVersion; - int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes - int64_t nExpiration; - int nID; - int nCancel; - std::set setCancel; - int nMinVer; // lowest version inclusive - int nMaxVer; // highest version inclusive - std::set setSubVer; // empty matches all - int nPriority; - - // Actions - std::string strComment; - std::string strStatusBar; - std::string strReserved; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(this->nVersion); - READWRITE(nRelayUntil); - READWRITE(nExpiration); - READWRITE(nID); - READWRITE(nCancel); - READWRITE(setCancel); - READWRITE(nMinVer); - READWRITE(nMaxVer); - READWRITE(setSubVer); - READWRITE(nPriority); - - READWRITE(LIMITED_STRING(strComment, 65536)); - READWRITE(LIMITED_STRING(strStatusBar, 256)); - READWRITE(LIMITED_STRING(strReserved, 256)); - } - - void SetNull(); - - std::string ToString() const; -}; - -/** An alert is a combination of a serialized CUnsignedAlert and a signature. */ -class CAlert : public CUnsignedAlert -{ -public: - std::vector vchMsg; - std::vector vchSig; - - CAlert() - { - SetNull(); - } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(vchMsg); - READWRITE(vchSig); - } - - void SetNull(); - bool IsNull() const; - uint256 GetHash() const; - bool IsInEffect() const; - bool Cancels(const CAlert& alert) const; - bool AppliesTo(int nVersion, const std::string& strSubVerIn) const; - bool AppliesToMe() const; - bool RelayTo(CNode* pnode, CConnman& connman) const; - bool Sign(); - bool CheckSignature(const std::vector& alertKey) const; - bool ProcessAlert(const std::vector& alertKey, bool fThread = true) const; // fThread means run -alertnotify in a free-running thread - static void Notify(const std::string& strMessage, bool fThread = true); - - /* - * Get copy of (active) alert object by hash. Returns a null alert if it is not found. - */ - static CAlert getAlertByHash(const uint256 &hash); -}; - -#endif // BITCOIN_ALERT_H diff --git a/src/chainparams.cpp b/src/chainparams.cpp index d4b18721f8a4..0c1770bc5473 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -283,7 +283,6 @@ class CMainParams : public CChainParams { pchMessageStart[1] = 0x0c; pchMessageStart[2] = 0x6b; pchMessageStart[3] = 0xbd; - vAlertPubKey = ParseHex("048240a8748a80a286b270ba126705ced4f2ce5a7847b3610ea3c06513150dade2a8512ed5ea86320824683fc0818f0ac019214973e677acd1244f6d0571fc5103"); nDefaultPort = 9999; nPruneAfterHeight = 100000; @@ -461,7 +460,6 @@ class CTestNetParams : public CChainParams { pchMessageStart[1] = 0xe2; pchMessageStart[2] = 0xca; pchMessageStart[3] = 0xff; - vAlertPubKey = ParseHex("04517d8a699cb43d3938d7b24faaff7cda448ca4ea267723ba614784de661949bf632d6304316b244646dea079735b9a6fc4af804efb4752075b9fe2245e14e412"); nDefaultPort = 19999; nPruneAfterHeight = 1000; @@ -620,7 +618,6 @@ class CDevNetParams : public CChainParams { pchMessageStart[1] = 0xca; pchMessageStart[2] = 0xff; pchMessageStart[3] = 0xce; - vAlertPubKey = ParseHex("04517d8a699cb43d3938d7b24faaff7cda448ca4ea267723ba614784de661949bf632d6304316b244646dea079735b9a6fc4af804efb4752075b9fe2245e14e412"); nDefaultPort = 19999; nPruneAfterHeight = 1000; diff --git a/src/chainparams.h b/src/chainparams.h index edcaeabfe574..12e4448680b6 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -58,7 +58,6 @@ class CChainParams const Consensus::Params& GetConsensus() const { return consensus; } const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } - const std::vector& AlertKey() const { return vAlertPubKey; } int GetDefaultPort() const { return nDefaultPort; } const CBlock& GenesisBlock() const { return genesis; } @@ -95,8 +94,6 @@ class CChainParams Consensus::Params consensus; CMessageHeader::MessageStartChars pchMessageStart; - //! Raw pub key bytes for the broadcast alert signing key. - std::vector vAlertPubKey; int nDefaultPort; uint64_t nPruneAfterHeight; std::vector vSeeds; diff --git a/src/init.cpp b/src/init.cpp index 20d2ff78f84b..95c9d900cd62 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -444,7 +444,6 @@ std::string HelpMessage(HelpMessageMode mode) std::string strUsage = HelpMessageGroup(_("Options:")); strUsage += HelpMessageOpt("-?", _("Print this help message and exit")); strUsage += HelpMessageOpt("-version", _("Print version and exit")); - strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS)); strUsage += HelpMessageOpt("-alertnotify=", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)")); strUsage += HelpMessageOpt("-blocknotify=", _("Execute command when the best block changes (%s in cmd is replaced by block hash)")); if (showDebug) @@ -1313,8 +1312,6 @@ bool AppInitParameterInteraction() fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER); nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes); - fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS); - // Option to startup with mocktime set (used for regression testing): SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op diff --git a/src/net_processing.cpp b/src/net_processing.cpp index cbc338ad1cb4..d159917e22f3 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -5,7 +5,6 @@ #include "net_processing.h" -#include "alert.h" #include "addrman.h" #include "arith_uint256.h" #include "blockencodings.h" @@ -1616,13 +1615,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr connman.MarkAddressGood(pfrom->addr); } - // Relay alerts - { - LOCK(cs_mapAlerts); - BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) - item.second.RelayTo(pfrom, connman); - } - std::string remoteAddr; if (fLogIPs) remoteAddr = ", peeraddr=" + pfrom->addr.ToString(); @@ -2926,37 +2918,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } - else if (fAlerts && strCommand == NetMsgType::ALERT) - { - CAlert alert; - vRecv >> alert; - - uint256 alertHash = alert.GetHash(); - if (pfrom->setKnown.count(alertHash) == 0) - { - if (alert.ProcessAlert(chainparams.AlertKey())) - { - // Relay - pfrom->setKnown.insert(alertHash); - { - connman.ForEachNode([&alert, &connman](CNode* pnode) { - alert.RelayTo(pnode, connman); - }); - } - } - else { - // Small DoS penalty so peers that send us lots of - // duplicate/expired/invalid-signature/whatever alerts - // eventually get banned. - // This isn't a Misbehaving(100) (immediate ban) because the - // peer might be an older or different implementation with - // a different signature key, etc. - Misbehaving(pfrom->GetId(), 10); - } - } - } - - else if (strCommand == NetMsgType::FILTERLOAD) { CBloomFilter filter; diff --git a/src/protocol.cpp b/src/protocol.cpp index a81ff290e5b1..48146ee8f9d4 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -28,7 +28,6 @@ const char *GETADDR="getaddr"; const char *MEMPOOL="mempool"; const char *PING="ping"; const char *PONG="pong"; -const char *ALERT="alert"; const char *NOTFOUND="notfound"; const char *FILTERLOAD="filterload"; const char *FILTERADD="filteradd"; @@ -132,7 +131,6 @@ const static std::string allNetMessageTypes[] = { NetMsgType::MEMPOOL, NetMsgType::PING, NetMsgType::PONG, - NetMsgType::ALERT, NetMsgType::NOTFOUND, NetMsgType::FILTERLOAD, NetMsgType::FILTERADD, diff --git a/src/protocol.h b/src/protocol.h index f4f949bf4e5c..bce6790c662a 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -160,13 +160,6 @@ extern const char *PING; * @see https://bitcoin.org/en/developer-reference#pong */ extern const char *PONG; -/** - * The alert message warns nodes of problems that may affect them or the rest - * of the network. - * @since protocol version 311. - * @see https://bitcoin.org/en/developer-reference#alert - */ -extern const char *ALERT; /** * The notfound message is a reply to a getdata message which requested an * object the receiving node does not have available for relay. diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 5f1927d4bb46..1836509e13d3 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -10,7 +10,6 @@ #include "guiutil.h" #include "peertablemodel.h" -#include "alert.h" #include "chain.h" #include "chainparams.h" #include "checkpoints.h" @@ -202,20 +201,8 @@ void ClientModel::updateNetworkActive(bool networkActive) Q_EMIT networkActiveChanged(networkActive); } -void ClientModel::updateAlert(const QString &hash, int status) +void ClientModel::updateAlert() { - // Show error message notification for new alert - if(status == CT_NEW) - { - uint256 hash_256; - hash_256.SetHex(hash.toStdString()); - CAlert alert = CAlert::getAlertByHash(hash_256); - if(!alert.IsNull()) - { - Q_EMIT message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR); - } - } - Q_EMIT alertsChanged(getStatusBarWarnings()); } @@ -323,12 +310,10 @@ static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkAct Q_ARG(bool, networkActive)); } -static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status) +static void NotifyAlertChanged(ClientModel *clientmodel) { - qDebug() << "NotifyAlertChanged: " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status); - QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(hash.GetHex())), - Q_ARG(int, status)); + qDebug() << "NotifyAlertChanged"; + QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection); } static void BannedListChanged(ClientModel *clientmodel) @@ -382,7 +367,7 @@ void ClientModel::subscribeToCoreSignals() uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyNetworkActiveChanged.connect(boost::bind(NotifyNetworkActiveChanged, this, _1)); - uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); + uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this)); uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this)); uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2, false)); uiInterface.NotifyHeaderTip.connect(boost::bind(BlockTipChanged, this, _1, _2, true)); @@ -396,7 +381,7 @@ void ClientModel::unsubscribeFromCoreSignals() uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyNetworkActiveChanged.disconnect(boost::bind(NotifyNetworkActiveChanged, this, _1)); - uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); + uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this)); uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this)); uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, false)); uiInterface.NotifyHeaderTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, true)); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 67ad63b41e6a..9c86be225683 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -69,7 +69,7 @@ class ClientModel : public QObject void setMasternodeList(const CDeterministicMNList& mnList); CDeterministicMNList getMasternodeList() const; void refreshMasternodeList(); - + quint64 getTotalBytesRecv() const; quint64 getTotalBytesSent() const; @@ -134,7 +134,7 @@ public Q_SLOTS: void updateTimer(); void updateNumConnections(int numConnections); void updateNetworkActive(bool networkActive); - void updateAlert(const QString &hash, int status); + void updateAlert(); void updateBanlist(); }; diff --git a/src/sendalert.cpp b/src/sendalert.cpp deleted file mode 100644 index 1aa8a0cbfc2f..000000000000 --- a/src/sendalert.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "alert.h" -#include "clientversion.h" -#include "chainparams.h" -#include "init.h" -#include "net.h" -#include "utilstrencodings.h" -#include "utiltime.h" - -/* -If you need to broadcast an alert, here's what to do: - -1. Modify alert parameters below, see alert.* and comments in the code - for what does what. - -2. run dashd with -printalert or -sendalert like this: - /path/to/dashd -printalert - -One minute after starting up the alert will be broadcast. It is then -flooded through the network until the nRelayUntil time, and will be -active until nExpiration OR the alert is cancelled. - -If you screw up something, send another alert with nCancel set to cancel -the bad alert. -*/ - -void ThreadSendAlert(CConnman& connman) -{ - if (!IsArgSet("-sendalert") && !IsArgSet("-printalert")) - return; - - // Wait one minute so we get well connected. If we only need to print - // but not to broadcast - do this right away. - if (IsArgSet("-sendalert")) - MilliSleep(60*1000); - - // - // Alerts are relayed around the network until nRelayUntil, flood - // filling to every node. - // After the relay time is past, new nodes are told about alerts - // when they connect to peers, until either nExpiration or - // the alert is cancelled by a newer alert. - // Nodes never save alerts to disk, they are in-memory-only. - // - CAlert alert; - alert.nRelayUntil = GetAdjustedTime() + 15 * 60; - alert.nExpiration = GetAdjustedTime() + 30 * 60 * 60; - alert.nID = 1; // keep track of alert IDs somewhere - alert.nCancel = 0; // cancels previous messages up to this ID number - - // These versions are protocol versions - alert.nMinVer = 70000; - alert.nMaxVer = 70103; - - // - // 1000 for Misc warnings like out of disk space and clock is wrong - // 2000 for longer invalid proof-of-work chain - // Higher numbers mean higher priority - alert.nPriority = 5000; - alert.strComment = ""; - alert.strStatusBar = "URGENT: Upgrade required: see https://www.dash.org"; - - // Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done: - // alert.setSubVer.insert(std::string("/Dash Core:0.12.0.58/")); - - // Sign - if(!alert.Sign()) - { - LogPrintf("ThreadSendAlert() : could not sign alert\n"); - return; - } - - // Test - CDataStream sBuffer(SER_NETWORK, CLIENT_VERSION); - sBuffer << alert; - CAlert alert2; - sBuffer >> alert2; - if (!alert2.CheckSignature(Params().AlertKey())) - { - printf("ThreadSendAlert() : CheckSignature failed\n"); - return; - } - assert(alert2.vchMsg == alert.vchMsg); - assert(alert2.vchSig == alert.vchSig); - alert.SetNull(); - printf("\nThreadSendAlert:\n"); - printf("hash=%s\n", alert2.GetHash().ToString().c_str()); - printf("%s", alert2.ToString().c_str()); - printf("vchMsg=%s\n", HexStr(alert2.vchMsg).c_str()); - printf("vchSig=%s\n", HexStr(alert2.vchSig).c_str()); - - // Confirm - if (!IsArgSet("-sendalert")) - return; - while (connman.GetNodeCount(CConnman::CONNECTIONS_ALL) == 0 && !ShutdownRequested()) - MilliSleep(500); - if (ShutdownRequested()) - return; - - // Send - printf("ThreadSendAlert() : Sending alert\n"); - int nSent = 0; - { - connman.ForEachNode([&alert2, &connman, &nSent](CNode* pnode) { - if (alert2.RelayTo(pnode, connman)) - { - printf("ThreadSendAlert() : Sent alert to %s\n", pnode->addr.ToString().c_str()); - nSent++; - } - }); - } - printf("ThreadSendAlert() : Alert sent to %d nodes\n", nSent); -} diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index a2a2d9d96d0e..c14ba0bcd5a9 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -4,232 +4,77 @@ // Unit tests for alert system -#include "alert.h" -#include "chain.h" #include "chainparams.h" -#include "clientversion.h" -#include "data/alertTests.raw.h" #include "fs.h" -#include "serialize.h" -#include "streams.h" -#include "utilstrencodings.h" +#include "main.h" // For PartitionCheck #include "test/testutil.h" #include "test/test_dash.h" -#include - #include -// -// Sign a CAlert and serialize it -// -bool SignAndSave(CAlert &alert) -{ - // Sign - if(!alert.Sign()) - { - printf("SignAndSave() : could not sign alert:\n%s", alert.ToString().c_str()); - return false; - } +BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup) - std::string strFilePath = "src/test/data/alertTests.raw"; - // open output file and associate it with CAutoFile - FILE *file = fopen(strFilePath.c_str(), "ab+"); - CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); - if (fileout.IsNull()) - return error("%s: Failed to open file %s", __func__, strFilePath); - try { - fileout << alert; - } - catch (std::exception &e) { - return error("%s: Serialize or I/O error - %s", __func__, e.what()); - } - fileout.fclose(); - return true; -} +static bool falseFunc() { return false; } -// -// alertTests contains 8 alerts, generated with this code -// -void GenerateAlertTests() +BOOST_AUTO_TEST_CASE(PartitionAlert) { - CAlert alert; - alert.nRelayUntil = 60; - alert.nExpiration = 24 * 60 * 60; - alert.nID = 1; - alert.nCancel = 0; // cancels previous messages up to this ID number - alert.nMinVer = 0; // These versions are protocol versions - alert.nMaxVer = 999001; - alert.nPriority = 1; - alert.strComment = "Alert comment"; - alert.strStatusBar = "Alert 1"; - - SignAndSave(alert); - - alert.setSubVer.insert(std::string("/Satoshi:0.1.0/")); - alert.strStatusBar = "Alert 1 for Satoshi 0.1.0"; - SignAndSave(alert); - - alert.setSubVer.insert(std::string("/Satoshi:0.2.0/")); - alert.strStatusBar = "Alert 1 for Satoshi 0.1.0, 0.2.0"; - SignAndSave(alert); - - alert.setSubVer.clear(); - ++alert.nID; - alert.nCancel = 1; - alert.nPriority = 100; - alert.strStatusBar = "Alert 2, cancels 1"; - SignAndSave(alert); - - alert.nExpiration += 60; - ++alert.nID; - SignAndSave(alert); - - ++alert.nID; - alert.nMinVer = 11; - alert.nMaxVer = 22; - SignAndSave(alert); - - ++alert.nID; - alert.strStatusBar = "Alert 2 for Satoshi 0.1.0"; - alert.setSubVer.insert(std::string("/Satoshi:0.1.0/")); - SignAndSave(alert); - - ++alert.nID; - alert.nMinVer = 0; - alert.nMaxVer = 999999; - alert.strStatusBar = "Evil Alert'; /bin/ls; echo '"; - alert.setSubVer.clear(); - SignAndSave(alert); -} - -struct ReadAlerts : public TestingSetup -{ - ReadAlerts() + // Test PartitionCheck + CCriticalSection csDummy; + CBlockIndex indexDummy[100]; + CChainParams& params = Params(CBaseChainParams::MAIN); + int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; + + // Generate fake blockchain timestamps relative to + // an arbitrary time: + int64_t now = 1427379054; + SetMockTime(now); + for (int i = 0; i < 100; i++) { - std::vector vch(raw_tests::alertTests, raw_tests::alertTests + sizeof(raw_tests::alertTests)); - CDataStream stream(vch, SER_DISK, CLIENT_VERSION); - try { - while (!stream.eof()) - { - CAlert alert; - stream >> alert; - alerts.push_back(alert); - } - } - catch (const std::exception&) { } + indexDummy[i].phashBlock = NULL; + if (i == 0) indexDummy[i].pprev = NULL; + else indexDummy[i].pprev = &indexDummy[i-1]; + indexDummy[i].nHeight = i; + indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing; + // Other members don't matter, the partition check code doesn't + // use them } - ~ReadAlerts() { } - - static std::vector read_lines(fs::path filepath) - { - std::vector result; - - std::ifstream f(filepath.string().c_str()); - std::string line; - while (std::getline(f,line)) - result.push_back(line); - - return result; - } - - std::vector alerts; -}; - -BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts) - -// Steps to generate alert tests: -// - update alerts in GenerateAlertTests() (optional) -// - enable code below (#if 1) -// - replace "fffffffffffffffffffffffffffffffffffffffffffffffffff" with the actual MAINNET privkey -// - recompile and run "/path/to/test_dash -t Alert_test" -// -// NOTE: make sure to disable code and remove alert privkey when you're done! -// -#if 0 -BOOST_AUTO_TEST_CASE(GenerateAlerts) -{ - SoftSetArg("-alertkey", "fffffffffffffffffffffffffffffffffffffffffffffffffff"); - GenerateAlertTests(); -} -#endif - -BOOST_AUTO_TEST_CASE(AlertApplies) -{ - SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - - for (const auto& alert : alerts) - { - BOOST_CHECK(alert.CheckSignature(alertKey)); - } - - BOOST_CHECK(alerts.size() >= 3); - - // Matches: - BOOST_CHECK(alerts[0].AppliesTo(1, "")); - BOOST_CHECK(alerts[0].AppliesTo(999001, "")); - BOOST_CHECK(alerts[0].AppliesTo(1, "/Satoshi:11.11.11/")); - - BOOST_CHECK(alerts[1].AppliesTo(1, "/Satoshi:0.1.0/")); - BOOST_CHECK(alerts[1].AppliesTo(999001, "/Satoshi:0.1.0/")); - - BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.1.0/")); - BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.2.0/")); - - // Don't match: - BOOST_CHECK(!alerts[0].AppliesTo(-1, "")); - BOOST_CHECK(!alerts[0].AppliesTo(999002, "")); - - BOOST_CHECK(!alerts[1].AppliesTo(1, "")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.1.0")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(-1, "/Satoshi:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(999002, "/Satoshi:0.1.0/")); - BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.2.0/")); - - BOOST_CHECK(!alerts[2].AppliesTo(1, "/Satoshi:0.3.0/")); - - SetMockTime(0); -} - - -BOOST_AUTO_TEST_CASE(AlertNotify) -{ - SetMockTime(11); - const std::vector& alertKey = Params(CBaseChainParams::MAIN).AlertKey(); - - fs::path temp = GetTempPath() / - fs::unique_path("alertnotify-%%%%.txt"); - - ForceSetArg("-alertnotify", std::string("echo %s >> ") + temp.string()); - - for (const auto& alert : alerts) - alert.ProcessAlert(alertKey, false); - - std::vector r = read_lines(temp); - BOOST_CHECK_EQUAL(r.size(), 4u); - -// Windows built-in echo semantics are different than posixy shells. Quotes and -// whitespace are printed literally. -#ifndef WIN32 - BOOST_CHECK_EQUAL(r[0], "Alert 1"); - BOOST_CHECK_EQUAL(r[1], "Alert 2, cancels 1"); - BOOST_CHECK_EQUAL(r[2], "Alert 2, cancels 1"); - BOOST_CHECK_EQUAL(r[3], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed -#else - BOOST_CHECK_EQUAL(r[0], "'Alert 1' "); - BOOST_CHECK_EQUAL(r[1], "'Alert 2, cancels 1' "); - BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' "); - BOOST_CHECK_EQUAL(r[3], "'Evil Alert; /bin/ls; echo ' "); -#endif - fs::remove(temp); + strMiscWarning = ""; + + // Test 1: chain with blocks every nPowTargetSpacing seconds, + // as normal, no worries: + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning); + + // Test 2: go 3.5 hours without a block, expect a warning: + now += 3*60*60+30*60; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(!strMiscWarning.empty()); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); + strMiscWarning = ""; + + // Test 3: test the "partition alerts only go off once per day" + // code: + now += 60*10; + SetMockTime(now); + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(strMiscWarning.empty()); + + // Test 4: get 2.5 times as many blocks as expected: + now += 60*60*24; // Pretend it is a day later + SetMockTime(now); + int64_t quickSpacing = nPowTargetSpacing*2/5; + for (int i = 0; i < 100; i++) // Tweak chain timestamps: + indexDummy[i].nTime = now - (100-i)*quickSpacing; + PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); + BOOST_CHECK(!strMiscWarning.empty()); + BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); + strMiscWarning = ""; SetMockTime(0); } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/test/data/alertTests.raw b/src/test/data/alertTests.raw deleted file mode 100644 index f58df4f18b19797c32546343af2a012f6981bd1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1280 zcmZ={WME*h0b&qn2n6vM7$78=$-oe4#}5(Vb<9aEDp5$z&&^HED`AK53>n-ET$mI} ztb`w5aF2F~cz3Ss>=|aB&+QYZR`ql&k-gflJ1=|d9wr50@t%g=vtMTRn7vvYY+^NK zc_MFE=l-iVu9#hXDDGMHBbg|NF!JjMCzj+FXJlF#=o#u6=!0~jI!qGkFom@IA_b^o z1+ZcUcLP@@MTY686MsLR)U(obx!~DHB}Y$(iEb;IGC^xI%b|6VQQO+iGbsdH&T1+D zrdx9AUFxyBhUcHuq_1L`^jPREHbxPc5YAZ8#X zq?Rz0{>rl#{hiufxLK9&{@1|tS9)nGugr2|m{!fd-PFjWkiY)riu?9YUPTqJITt9g zg*|K;d(4;LN#9PNdaQo5MWY8Lv%o@%72Q!7nFZ64(9B|lC9{C@wW@xbuN3o%#7a%R zx$hbHH7~v`$YXfU*8NV=sH#ar zcGW6Xe~aI|`iR7Qmm^Z=|D6n($x>NX=G-mv;UIVE!&+cQNGz$aPkL;n@b|(3Ybh;x V?io9GZ{K@V|6#?ksoGu)9RL~Vf)M}! diff --git a/src/ui_interface.h b/src/ui_interface.h index 9d5ad977ee6b..cb07bc0c867c 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -90,10 +90,9 @@ class CClientUIInterface boost::signals2::signal NotifyNetworkActiveChanged; /** - * New, updated or cancelled alert. - * @note called with lock cs_mapAlerts held. + * Status bar alerts changed. */ - boost::signals2::signal NotifyAlertChanged; + boost::signals2::signal NotifyAlertChanged; /** A wallet has been loaded. */ boost::signals2::signal LoadWallet; diff --git a/src/validation.cpp b/src/validation.cpp index e49206cf3102..3a9533780f2b 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -6,7 +6,6 @@ #include "validation.h" -#include "alert.h" #include "arith_uint256.h" #include "blockencodings.h" #include "chain.h" @@ -92,7 +91,6 @@ bool fCheckBlockIndex = false; bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; size_t nCoinCacheUsage = 5000 * 300; uint64_t nPruneTarget = 0; -bool fAlerts = DEFAULT_ALERTS; int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; std::atomic fDIP0001ActiveAtTip{false}; @@ -1206,6 +1204,26 @@ bool IsInitialBlockDownload() CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL; +static void AlertNotify(const std::string& strMessage, bool fThread) +{ + uiInterface.NotifyAlertChanged(); + std::string strCmd = GetArg("-alertnotify", ""); + if (strCmd.empty()) return; + + // Alert text should be plain ascii coming from a trusted source, but to + // be safe we first strip anything not in safeChars, then add single quotes around + // the whole string before passing it to the shell: + std::string singleQuote("'"); + std::string safeStatus = SanitizeString(strMessage); + safeStatus = singleQuote+safeStatus+singleQuote; + boost::replace_all(strCmd, "%s", safeStatus); + + if (fThread) + boost::thread t(runCommand, strCmd); // thread runs free + else + runCommand(strCmd); +} + static void CheckForkWarningConditions() { AssertLockHeld(cs_main); @@ -1226,7 +1244,7 @@ static void CheckForkWarningConditions() if(pindexBestForkBase->phashBlock){ std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") + pindexBestForkBase->phashBlock->ToString() + std::string("'"); - CAlert::Notify(warning); + AlertNotify(warning); } } if (pindexBestForkTip && pindexBestForkBase) @@ -2462,7 +2480,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { std::string strWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit); SetMiscWarning(strWarning); if (!fWarned) { - CAlert::Notify(strWarning); + AlertNotify(strWarning); fWarned = true; } } else { @@ -2486,7 +2504,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { // notify GetWarnings(), called by Qt and the JSON-RPC code to warn the user: SetMiscWarning(strWarning); if (!fWarned) { - CAlert::Notify(strWarning); + AlertNotify(strWarning); fWarned = true; } } diff --git a/src/validation.h b/src/validation.h index 1982f0d12c49..5a9285bff477 100644 --- a/src/validation.h +++ b/src/validation.h @@ -50,8 +50,6 @@ struct ChainTxData; struct LockPoints; -/** Default for accepting alerts from the P2P network. */ -static const bool DEFAULT_ALERTS = true; /** Default for DEFAULT_WHITELISTRELAY. */ static const bool DEFAULT_WHITELISTRELAY = true; /** Default for DEFAULT_WHITELISTFORCERELAY. */ @@ -184,7 +182,6 @@ extern size_t nCoinCacheUsage; extern CFeeRate minRelayTxFee; /** Absolute maximum transaction fee (in duffs) used by wallet and mempool (rejects high fee in sendrawtransaction) */ extern CAmount maxTxFee; -extern bool fAlerts; /** If the tip is older than this (in seconds), the node is considered to be in initial block download. */ extern int64_t nMaxTipAge; diff --git a/src/warnings.cpp b/src/warnings.cpp index f4f2bc54891c..8c58998039df 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -7,7 +7,6 @@ #include "clientversion.h" #include "util.h" #include "warnings.h" -#include "alert.h" #include "hash.h" CCriticalSection cs_warnings; @@ -47,7 +46,6 @@ bool GetfLargeWorkInvalidChainFound() std::string GetWarnings(const std::string& strFor) { - int nPriority = 0; std::string strStatusBar; std::string strRPC; std::string strGUI; @@ -66,38 +64,21 @@ std::string GetWarnings(const std::string& strFor) // Misc warnings like out of disk space and clock is wrong if (strMiscWarning != "") { - nPriority = 1000; strStatusBar = strMiscWarning; strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + strMiscWarning; } if (fLargeWorkForkFound) { - nPriority = 2000; strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."; strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues."); } else if (fLargeWorkInvalidChainFound) { - nPriority = 2000; strStatusBar = strRPC = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."; strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade."); } - // Alerts - { - LOCK(cs_mapAlerts); - for (const auto& item : mapAlerts) - { - const CAlert& alert = item.second; - if (alert.AppliesToMe() && alert.nPriority > nPriority) - { - nPriority = alert.nPriority; - strStatusBar = strGUI = alert.strStatusBar; - } - } - } - if (strFor == "gui") return strGUI; else if (strFor == "statusbar") From c6b926547ca2f818dd0b6cde213fe9d7e4438ab9 Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 20:16:26 -0500 Subject: [PATCH 242/987] Merge #7958: Remove useless argument to AlertNotify. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit b02119e Remove useless argument to AlertNotify. (Pavel Janík) Signed-off-by: Pasta # Conflicts: # src/main.cpp --- src/validation.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 3a9533780f2b..042b08d9e9bc 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1204,7 +1204,7 @@ bool IsInitialBlockDownload() CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL; -static void AlertNotify(const std::string& strMessage, bool fThread) +static void AlertNotify(const std::string& strMessage) { uiInterface.NotifyAlertChanged(); std::string strCmd = GetArg("-alertnotify", ""); @@ -1218,10 +1218,7 @@ static void AlertNotify(const std::string& strMessage, bool fThread) safeStatus = singleQuote+safeStatus+singleQuote; boost::replace_all(strCmd, "%s", safeStatus); - if (fThread) - boost::thread t(runCommand, strCmd); // thread runs free - else - runCommand(strCmd); + boost::thread t(runCommand, strCmd); // thread runs free } static void CheckForkWarningConditions() From ce6623eba8a1c04458e0ee245d858a3c5419a21d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 6 Jul 2016 07:35:39 +0200 Subject: [PATCH 243/987] Remove stale code, delete alert_tests.cpp --- src/Makefile.test.include | 1 - src/test/alert_tests.cpp | 80 --------------------------------------- 2 files changed, 81 deletions(-) delete mode 100644 src/test/alert_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index bd9ef26db6d9..f3542319b6e3 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -28,7 +28,6 @@ BITCOIN_TESTS =\ test/arith_uint256_tests.cpp \ test/scriptnum10.h \ test/addrman_tests.cpp \ - test/alert_tests.cpp \ test/amount_tests.cpp \ test/allocator_tests.cpp \ test/base32_tests.cpp \ diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp deleted file mode 100644 index c14ba0bcd5a9..000000000000 --- a/src/test/alert_tests.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2013-2015 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -// Unit tests for alert system - -#include "chainparams.h" -#include "fs.h" -#include "main.h" // For PartitionCheck - -#include "test/testutil.h" -#include "test/test_dash.h" - -#include - -BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup) - - -static bool falseFunc() { return false; } - -BOOST_AUTO_TEST_CASE(PartitionAlert) -{ - // Test PartitionCheck - CCriticalSection csDummy; - CBlockIndex indexDummy[100]; - CChainParams& params = Params(CBaseChainParams::MAIN); - int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing; - - // Generate fake blockchain timestamps relative to - // an arbitrary time: - int64_t now = 1427379054; - SetMockTime(now); - for (int i = 0; i < 100; i++) - { - indexDummy[i].phashBlock = NULL; - if (i == 0) indexDummy[i].pprev = NULL; - else indexDummy[i].pprev = &indexDummy[i-1]; - indexDummy[i].nHeight = i; - indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing; - // Other members don't matter, the partition check code doesn't - // use them - } - - strMiscWarning = ""; - - // Test 1: chain with blocks every nPowTargetSpacing seconds, - // as normal, no worries: - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning); - - // Test 2: go 3.5 hours without a block, expect a warning: - now += 3*60*60+30*60; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; - - // Test 3: test the "partition alerts only go off once per day" - // code: - now += 60*10; - SetMockTime(now); - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(strMiscWarning.empty()); - - // Test 4: get 2.5 times as many blocks as expected: - now += 60*60*24; // Pretend it is a day later - SetMockTime(now); - int64_t quickSpacing = nPowTargetSpacing*2/5; - for (int i = 0; i < 100; i++) // Tweak chain timestamps: - indexDummy[i].nTime = now - (100-i)*quickSpacing; - PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing); - BOOST_CHECK(!strMiscWarning.empty()); - BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning); - strMiscWarning = ""; - - SetMockTime(0); -} - -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 26ec979fa3f2a02828d8f8c5df2f686f7fa1c146 Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 20:42:07 -0500 Subject: [PATCH 244/987] remove TheadSendAlert in init.cpp Signed-off-by: Pasta --- src/init.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 95c9d900cd62..3cb8cb01094b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -97,8 +97,6 @@ #include "zmq/zmqnotificationinterface.h" #endif -extern void ThreadSendAlert(CConnman& connman); - bool fFeeEstimatesInitialized = false; static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_REST_ENABLE = false; @@ -2162,7 +2160,5 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) pwalletMain->postInitProcess(scheduler); #endif - threadGroup.create_thread(boost::bind(&ThreadSendAlert, boost::ref(connman))); - return !fRequestShutdown; } From 0e556be703dd3fd563c0134173baaf6f1cb2ff44 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 15 May 2017 07:30:09 +0200 Subject: [PATCH 245/987] Merge #9494: Introduce an ArgsManager class encapsulating cs_args, mapArgs and mapMultiArgs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 78da882 Util: Small improvements in gArgs usage (Jorge Timón) 5292245 Util: Put mapMultiArgs inside ArgsManager (Jorge Timón) b3cbd55 scripted-diff: Util: Encapsulate mapMultiArgs behind gArgs (Jorge Timón) f2957ce Util: Create ArgsManager class... (Jorge Timón) Tree-SHA512: 7d58250da440ad0f41745f46ab6021d6ecbb292035cab3d86fb08ce6bd822df604ac31b3ded6fd6914f7cfd12ba531cbc06a76eb500f629627f47ae6ac8350a7 add ForceRemoveArg and ForceSetMultiArg to ArgsManager class Signed-off-by: Pasta add static inlines for ForceSetMultiArgs and ForceRemoveArg Signed-off-by: Pasta both void Signed-off-by: Pasta use gArgs, dash code Signed-off-by: Pasta revert a bit Signed-off-by: Pasta adj Signed-off-by: Pasta use gArgs Signed-off-by: Pasta remove '_' Signed-off-by: Pasta --- src/httprpc.cpp | 4 +-- src/httpserver.cpp | 12 +++---- src/init.cpp | 70 ++++++++++++++++++------------------- src/net.cpp | 12 +++---- src/test/util_tests.cpp | 77 ++++++++++++++++++++++++----------------- src/util.cpp | 47 +++++++++++++------------ src/util.h | 73 ++++++++++++++++++++++++++++++++++++-- 7 files changed, 188 insertions(+), 107 deletions(-) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index c7241bf4dbbc..7fe821328593 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -93,9 +93,9 @@ static bool multiUserAuthorized(std::string strUserPass) std::string strUser = strUserPass.substr(0, strUserPass.find(":")); std::string strPass = strUserPass.substr(strUserPass.find(":") + 1); - if (mapMultiArgs.count("-rpcauth") > 0) { + if (gArgs.IsArgSet("-rpcauth")) { //Search for multi-user login/pass "rpcauth" from config - BOOST_FOREACH(std::string strRPCAuth, mapMultiArgs.at("-rpcauth")) + BOOST_FOREACH(std::string strRPCAuth, gArgs.GetArgs("-rpcauth")) { std::vector vFields; boost::split(vFields, strRPCAuth, boost::is_any_of(":$")); diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 696fc0c14b61..e81a6d89ecd1 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -197,9 +197,8 @@ static bool InitHTTPAllowList() LookupHost("::1", localv6, false); rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost - if (mapMultiArgs.count("-rpcallowip")) { - const std::vector& vAllow = mapMultiArgs.at("-rpcallowip"); - for (std::string strAllow : vAllow) { + if (gArgs.IsArgSet("-rpcallowip")) { + for (const std::string& strAllow : gArgs.GetArgs("-rpcallowip")) { CSubNet subnet; LookupSubNet(strAllow.c_str(), subnet); if (!subnet.IsValid()) { @@ -322,12 +321,11 @@ static bool HTTPBindAddresses(struct evhttp* http) if (IsArgSet("-rpcbind")) { LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n"); } - } else if (mapMultiArgs.count("-rpcbind")) { // Specific bind address - const std::vector& vbind = mapMultiArgs.at("-rpcbind"); - for (std::vector::const_iterator i = vbind.begin(); i != vbind.end(); ++i) { + } else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address + for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) { int port = defaultPort; std::string host; - SplitHostPort(*i, port, host); + SplitHostPort(strRPCBind, port, host); endpoints.push_back(std::make_pair(host, port)); } } else { // No specific bind address specified, bind to any diff --git a/src/init.cpp b/src/init.cpp index 3cb8cb01094b..4e1b639d8e60 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -917,7 +917,7 @@ void InitParameterInteraction() } } - if (mapMultiArgs.count("-connect") && mapMultiArgs.at("-connect").size() > 0) { + if (gArgs.IsArgSet("-connect")) { // when only connecting to trusted nodes, do not seed via DNS, or listen by default if (SoftSetBoolArg("-dnsseed", false)) LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__); @@ -1109,21 +1109,23 @@ bool AppInitParameterInteraction() if (IsArgSet("-devnet")) { // Require setting of ports when running devnet - if (GetArg("-listen", DEFAULT_LISTEN) && !IsArgSet("-port")) + if (GetArg("-listen", DEFAULT_LISTEN) && !IsArgSet("-port")) { return InitError(_("-port must be specified when -devnet and -listen are specified")); - if (GetArg("-server", false) && !IsArgSet("-rpcport")) + } + if (GetArg("-server", false) && !IsArgSet("-rpcport")) { return InitError(_("-rpcport must be specified when -devnet and -server are specified")); - - if (mapMultiArgs.count("-devnet") > 1) + } + if (gArgs.IsArgSet("-devnet")) { return InitError(_("-devnet can only be specified once")); + } } fAllowPrivateNet = GetBoolArg("-allowprivatenet", DEFAULT_ALLOWPRIVATENET); // Make sure enough file descriptors are available int nBind = std::max( - (mapMultiArgs.count("-bind") ? mapMultiArgs.at("-bind").size() : 0) + - (mapMultiArgs.count("-whitebind") ? mapMultiArgs.at("-whitebind").size() : 0), size_t(1)); + (gArgs.IsArgSet("-bind") ? gArgs.GetArgs("-bind").size() : 0) + + (gArgs.IsArgSet("-whitebind") ? gArgs.GetArgs("-whitebind").size() : 0), size_t(1)); nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); nMaxConnections = std::max(nUserMaxConnections, 0); @@ -1139,9 +1141,9 @@ bool AppInitParameterInteraction() // ********************************************************* Step 3: parameter-to-internal-flags - if (mapMultiArgs.count("-debug") > 0) { + if (gArgs.IsArgSet("-debug")) { // Special-case: if -debug=0/-nodebug is set, turn off debugging messages - const std::vector& categories = mapMultiArgs.at("-debug"); + const std::vector categories = gArgs.GetArgs("-debug"); if (!(GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), std::string("0")) != categories.end())) { for (const auto& cat : categories) { @@ -1155,9 +1157,8 @@ bool AppInitParameterInteraction() } // Now remove the logging categories which were explicitly excluded - if (mapMultiArgs.count("-debugexclude") > 0) { - const std::vector& excludedCategories = mapMultiArgs.at("-debugexclude"); - for (const auto& cat : excludedCategories) { + if (gArgs.IsArgSet("-debugexclude")) { + for (const std::string& cat : gArgs.GetArgs("-debugexclude")) { uint64_t flag; if (!GetLogCategory(&flag, &cat)) { InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat)); @@ -1318,15 +1319,14 @@ bool AppInitParameterInteraction() nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE); - if (mapMultiArgs.count("-bip9params")) { + if (gArgs.IsArgSet("-bip9params")) { // Allow overriding BIP9 parameters for testing if (!chainparams.MineBlocksOnDemand()) { return InitError("BIP9 parameters may only be overridden on regtest."); } - const std::vector& deployments = mapMultiArgs.at("-bip9params"); - for (auto i : deployments) { + for (const std::string& strDeployment : gArgs.GetArgs("-bip9params")) { std::vector vDeploymentParams; - boost::split(vDeploymentParams, i, boost::is_any_of(":")); + boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":")); if (vDeploymentParams.size() != 3 && vDeploymentParams.size() != 5) { return InitError("BIP9 parameters malformed, expecting deployment:start:end or deployment:start:end:window:threshold"); } @@ -1515,8 +1515,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } std::vector vSporkAddresses; - if (mapMultiArgs.count("-sporkaddr")) { - vSporkAddresses = mapMultiArgs.at("-sporkaddr"); + if (gArgs.IsArgSet("-sporkaddr")) { + vSporkAddresses = gArgs.GetArgs("-sporkaddr"); } else { vSporkAddresses = Params().SporkAddresses(); } @@ -1587,8 +1587,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) uacomments.push_back(strprintf("devnet=%s", GetDevNetName())); } - if (mapMultiArgs.count("-uacomment")) { - BOOST_FOREACH(std::string cmt, mapMultiArgs.at("-uacomment")) + if (gArgs.IsArgSet("-uacomment")) { + BOOST_FOREACH(std::string cmt, gArgs.GetArgs("-uacomment")) { if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt)); @@ -1601,9 +1601,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) strSubVersion.size(), MAX_SUBVERSION_LENGTH)); } - if (mapMultiArgs.count("-onlynet")) { + if (gArgs.IsArgSet("-onlynet")) { std::set nets; - BOOST_FOREACH(const std::string& snet, mapMultiArgs.at("-onlynet")) { + BOOST_FOREACH(const std::string& snet, gArgs.GetArgs("-onlynet")) { enum Network net = ParseNetwork(snet); if (net == NET_UNROUTABLE) return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet)); @@ -1616,8 +1616,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } } - if (mapMultiArgs.count("-whitelist")) { - BOOST_FOREACH(const std::string& net, mapMultiArgs.at("-whitelist")) { + if (gArgs.IsArgSet("-whitelist")) { + BOOST_FOREACH(const std::string& net, gArgs.GetArgs("-whitelist")) { CSubNet subnet; LookupSubNet(net.c_str(), subnet); if (!subnet.IsValid()) @@ -1678,16 +1678,16 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) if (fListen) { bool fBound = false; - if (mapMultiArgs.count("-bind")) { - BOOST_FOREACH(const std::string& strBind, mapMultiArgs.at("-bind")) { + if (gArgs.IsArgSet("-bind")) { + BOOST_FOREACH(const std::string& strBind, gArgs.GetArgs("-bind")) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) return InitError(ResolveErrMsg("bind", strBind)); fBound |= Bind(connman, addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); } } - if (mapMultiArgs.count("-whitebind")) { - BOOST_FOREACH(const std::string& strBind, mapMultiArgs.at("-whitebind")) { + if (gArgs.IsArgSet("-whitebind")) { + BOOST_FOREACH(const std::string& strBind, gArgs.GetArgs("-whitebind")) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, 0, false)) return InitError(ResolveErrMsg("whitebind", strBind)); @@ -1696,7 +1696,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) fBound |= Bind(connman, addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST)); } } - if (!mapMultiArgs.count("-bind") && !mapMultiArgs.count("-whitebind")) { + if (!gArgs.IsArgSet("-bind") && !gArgs.IsArgSet("-whitebind")) { struct in_addr inaddr_any; inaddr_any.s_addr = INADDR_ANY; fBound |= Bind(connman, CService((in6_addr)IN6ADDR_ANY_INIT, GetListenPort()), BF_NONE); @@ -1706,8 +1706,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) return InitError(_("Failed to listen on any port. Use -listen=0 if you want this.")); } - if (mapMultiArgs.count("-externalip")) { - BOOST_FOREACH(const std::string& strAddr, mapMultiArgs.at("-externalip")) { + if (gArgs.IsArgSet("-externalip")) { + BOOST_FOREACH(const std::string& strAddr, gArgs.GetArgs("-externalip")) { CService addrLocal; if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid()) AddLocal(addrLocal, LOCAL_MANUAL); @@ -1716,8 +1716,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } } - if (mapMultiArgs.count("-seednode")) { - BOOST_FOREACH(const std::string& strDest, mapMultiArgs.at("-seednode")) + if (gArgs.IsArgSet("-seednode")) { + BOOST_FOREACH(const std::string& strDest, gArgs.GetArgs("-seednode")) connman.AddOneShot(strDest); } @@ -2101,9 +2101,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); std::vector vImportFiles; - if (mapMultiArgs.count("-loadblock")) + if (gArgs.IsArgSet("-loadblock")) { - BOOST_FOREACH(const std::string& strFile, mapMultiArgs.at("-loadblock")) + BOOST_FOREACH(const std::string& strFile, gArgs.GetArgs("-loadblock")) vImportFiles.push_back(strFile); } diff --git a/src/net.cpp b/src/net.cpp index 5d55e46d950b..d141708923c2 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1777,12 +1777,12 @@ void CConnman::ProcessOneShot() void CConnman::ThreadOpenConnections() { // Connect to specific addresses - if (mapMultiArgs.count("-connect") && mapMultiArgs.at("-connect").size() > 0) + if (gArgs.IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0) { for (int64_t nLoop = 0;; nLoop++) { ProcessOneShot(); - BOOST_FOREACH(const std::string& strAddr, mapMultiArgs.at("-connect")) + BOOST_FOREACH(const std::string& strAddr, gArgs.GetArgs("-connect")) { CAddress addr(CService(), NODE_NONE); OpenNetworkConnection(addr, false, NULL, strAddr.c_str()); @@ -2013,8 +2013,8 @@ void CConnman::ThreadOpenAddedConnections() { { LOCK(cs_vAddedNodes); - if (mapMultiArgs.count("-addnode")) - vAddedNodes = mapMultiArgs.at("-addnode"); + if (gArgs.IsArgSet("-addnode")) + vAddedNodes = gArgs.GetArgs("-addnode"); } while (true) @@ -2047,7 +2047,7 @@ void CConnman::ThreadOpenAddedConnections() void CConnman::ThreadOpenMasternodeConnections() { // Connecting to specific addresses, no masternode connections available - if (IsArgSet("-connect") && mapMultiArgs.at("-connect").size() > 0) + if (IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0) return; while (!interruptNet) @@ -2533,7 +2533,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c threadOpenAddedConnections = std::thread(&TraceThread >, "addcon", std::function(std::bind(&CConnman::ThreadOpenAddedConnections, this))); // Initiate outbound connections unless connect=0 - if (!mapMultiArgs.count("-connect") || mapMultiArgs.at("-connect").size() != 1 || mapMultiArgs.at("-connect")[0] != "0") + if (!gArgs.IsArgSet("-connect") || gArgs.GetArgs("-connect").size() != 1 || gArgs.GetArgs("-connect")[0] != "0") threadOpenConnections = std::thread(&TraceThread >, "opencon", std::function(std::bind(&CConnman::ThreadOpenConnections, this))); // Initiate masternode connections diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 910a17554ba3..45c8de288130 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -17,8 +17,6 @@ #include -extern std::unordered_map mapArgs; - BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(util_criticalsection) @@ -100,52 +98,67 @@ BOOST_AUTO_TEST_CASE(util_DateTimeStrFormat) BOOST_CHECK_EQUAL(DateTimeStrFormat("%a, %d %b %Y %H:%M:%S +0000", 1317425777), "Fri, 30 Sep 2011 23:36:17 +0000"); } +class TestArgsManager : public ArgsManager +{ +public: + std::map& GetMapArgs() + { + return mapArgs; + }; + const std::map >& GetMapMultiArgs() + { + return mapMultiArgs; + }; +}; + BOOST_AUTO_TEST_CASE(util_ParseParameters) { + TestArgsManager testArgs; const char *argv_test[] = {"-ignored", "-a", "-b", "-ccc=argument", "-ccc=multiple", "f", "-d=e"}; - ParseParameters(0, (char**)argv_test); - BOOST_CHECK(mapArgs.empty() && mapMultiArgs.empty()); + testArgs.ParseParameters(0, (char**)argv_test); + BOOST_CHECK(testArgs.GetMapArgs().empty() && testArgs.GetMapMultiArgs().empty()); - ParseParameters(1, (char**)argv_test); - BOOST_CHECK(mapArgs.empty() && mapMultiArgs.empty()); + testArgs.ParseParameters(1, (char**)argv_test); + BOOST_CHECK(testArgs.GetMapArgs().empty() && testArgs.GetMapMultiArgs().empty()); - ParseParameters(5, (char**)argv_test); + testArgs.ParseParameters(5, (char**)argv_test); // expectation: -ignored is ignored (program name argument), // -a, -b and -ccc end up in map, -d ignored because it is after // a non-option argument (non-GNU option parsing) - BOOST_CHECK(mapArgs.size() == 3 && mapMultiArgs.size() == 3); - BOOST_CHECK(IsArgSet("-a") && IsArgSet("-b") && IsArgSet("-ccc") - && !IsArgSet("f") && !IsArgSet("-d")); - BOOST_CHECK(mapMultiArgs.count("-a") && mapMultiArgs.count("-b") && mapMultiArgs.count("-ccc") - && !mapMultiArgs.count("f") && !mapMultiArgs.count("-d")); - - BOOST_CHECK(mapArgs["-a"] == "" && mapArgs["-ccc"] == "multiple"); - BOOST_CHECK(mapMultiArgs.at("-ccc").size() == 2); + BOOST_CHECK(testArgs.GetMapArgs().size() == 3 && testArgs.GetMapMultiArgs().size() == 3); + BOOST_CHECK(testArgs.IsArgSet("-a") && testArgs.IsArgSet("-b") && testArgs.IsArgSet("-ccc") + && !testArgs.IsArgSet("f") && !testArgs.IsArgSet("-d")); + BOOST_CHECK(testArgs.GetMapMultiArgs().count("-a") && testArgs.GetMapMultiArgs().count("-b") && testArgs.GetMapMultiArgs().count("-ccc") + && !testArgs.GetMapMultiArgs().count("f") && !testArgs.GetMapMultiArgs().count("-d")); + + BOOST_CHECK(testArgs.GetMapArgs()["-a"] == "" && testArgs.GetMapArgs()["-ccc"] == "multiple"); + BOOST_CHECK(testArgs.GetArgs("-ccc").size() == 2); } BOOST_AUTO_TEST_CASE(util_GetArg) { - mapArgs.clear(); - mapArgs["strtest1"] = "string..."; + TestArgsManager testArgs; + testArgs.GetMapArgs().clear(); + testArgs.GetMapArgs()["strtest1"] = "string..."; // strtest2 undefined on purpose - mapArgs["inttest1"] = "12345"; - mapArgs["inttest2"] = "81985529216486895"; + testArgs.GetMapArgs()["inttest1"] = "12345"; + testArgs.GetMapArgs()["inttest2"] = "81985529216486895"; // inttest3 undefined on purpose - mapArgs["booltest1"] = ""; + testArgs.GetMapArgs()["booltest1"] = ""; // booltest2 undefined on purpose - mapArgs["booltest3"] = "0"; - mapArgs["booltest4"] = "1"; - - BOOST_CHECK_EQUAL(GetArg("strtest1", "default"), "string..."); - BOOST_CHECK_EQUAL(GetArg("strtest2", "default"), "default"); - BOOST_CHECK_EQUAL(GetArg("inttest1", -1), 12345); - BOOST_CHECK_EQUAL(GetArg("inttest2", -1), 81985529216486895LL); - BOOST_CHECK_EQUAL(GetArg("inttest3", -1), -1); - BOOST_CHECK_EQUAL(GetBoolArg("booltest1", false), true); - BOOST_CHECK_EQUAL(GetBoolArg("booltest2", false), false); - BOOST_CHECK_EQUAL(GetBoolArg("booltest3", false), false); - BOOST_CHECK_EQUAL(GetBoolArg("booltest4", false), true); + testArgs.GetMapArgs()["booltest3"] = "0"; + testArgs.GetMapArgs()["booltest4"] = "1"; + + BOOST_CHECK_EQUAL(testArgs.GetArg("strtest1", "default"), "string..."); + BOOST_CHECK_EQUAL(testArgs.GetArg("strtest2", "default"), "default"); + BOOST_CHECK_EQUAL(testArgs.GetArg("inttest1", -1), 12345); + BOOST_CHECK_EQUAL(testArgs.GetArg("inttest2", -1), 81985529216486895LL); + BOOST_CHECK_EQUAL(testArgs.GetArg("inttest3", -1), -1); + BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest1", false), true); + BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest2", false), false); + BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest3", false), false); + BOOST_CHECK_EQUAL(testArgs.GetBoolArg("booltest4", false), true); } BOOST_AUTO_TEST_CASE(util_FormatMoney) diff --git a/src/util.cpp b/src/util.cpp index 6f1407f8025a..cb2054a56124 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -17,7 +17,6 @@ #include "random.h" #include "serialize.h" #include "stacktraces.h" -#include "sync.h" #include "utilstrencodings.h" #include "utiltime.h" @@ -110,10 +109,7 @@ int nWalletBackups = 10; const char * const BITCOIN_CONF_FILENAME = "dash.conf"; const char * const BITCOIN_PID_FILENAME = "dashd.pid"; -CCriticalSection cs_args; -std::unordered_map mapArgs; -static std::unordered_map > _mapMultiArgs; -const std::unordered_map >& mapMultiArgs = _mapMultiArgs; +ArgsManager gArgs; bool fPrintToConsole = false; bool fPrintToDebugLog = true; @@ -480,11 +476,11 @@ static void InterpretNegativeSetting(std::string& strKey, std::string& strValue) } } -void ParseParameters(int argc, const char* const argv[]) +void ArgsManager::ParseParameters(int argc, const char* const argv[]) { LOCK(cs_args); mapArgs.clear(); - _mapMultiArgs.clear(); + mapMultiArgs.clear(); for (int i = 1; i < argc; i++) { @@ -512,17 +508,23 @@ void ParseParameters(int argc, const char* const argv[]) InterpretNegativeSetting(str, strValue); mapArgs[str] = strValue; - _mapMultiArgs[str].push_back(strValue); + mapMultiArgs[str].push_back(strValue); } } -bool IsArgSet(const std::string& strArg) +std::vector ArgsManager::GetArgs(const std::string& strArg) +{ + LOCK(cs_args); + return mapMultiArgs.at(strArg); +} + +bool ArgsManager::IsArgSet(const std::string& strArg) { LOCK(cs_args); return mapArgs.count(strArg); } -std::string GetArg(const std::string& strArg, const std::string& strDefault) +std::string ArgsManager::GetArg(const std::string& strArg, const std::string& strDefault) { LOCK(cs_args); if (mapArgs.count(strArg)) @@ -530,7 +532,7 @@ std::string GetArg(const std::string& strArg, const std::string& strDefault) return strDefault; } -int64_t GetArg(const std::string& strArg, int64_t nDefault) +int64_t ArgsManager::GetArg(const std::string& strArg, int64_t nDefault) { LOCK(cs_args); if (mapArgs.count(strArg)) @@ -538,7 +540,7 @@ int64_t GetArg(const std::string& strArg, int64_t nDefault) return nDefault; } -bool GetBoolArg(const std::string& strArg, bool fDefault) +bool ArgsManager::GetBoolArg(const std::string& strArg, bool fDefault) { LOCK(cs_args); if (mapArgs.count(strArg)) @@ -546,16 +548,16 @@ bool GetBoolArg(const std::string& strArg, bool fDefault) return fDefault; } -bool SoftSetArg(const std::string& strArg, const std::string& strValue) +bool ArgsManager::SoftSetArg(const std::string& strArg, const std::string& strValue) { LOCK(cs_args); if (mapArgs.count(strArg)) return false; - mapArgs[strArg] = strValue; + ForceSetArg(strArg, strValue); return true; } -bool SoftSetBoolArg(const std::string& strArg, bool fValue) +bool ArgsManager::SoftSetBoolArg(const std::string& strArg, bool fValue) { if (fValue) return SoftSetArg(strArg, std::string("1")); @@ -563,23 +565,24 @@ bool SoftSetBoolArg(const std::string& strArg, bool fValue) return SoftSetArg(strArg, std::string("0")); } -void ForceSetArg(const std::string& strArg, const std::string& strValue) +void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strValue) { LOCK(cs_args); mapArgs[strArg] = strValue; + mapMultiArgs[strArg].push_back(strValue); } -void ForceSetMultiArgs(const std::string& strArg, const std::vector& values) +void ArgsManager::ForceSetMultiArgs(const std::string& strArg, const std::vector& values) { LOCK(cs_args); - _mapMultiArgs[strArg] = values; + mapMultiArgs[strArg] = values; } -void ForceRemoveArg(const std::string& strArg) +void ArgsManager::ForceRemoveArg(const std::string& strArg) { LOCK(cs_args); mapArgs.erase(strArg); - _mapMultiArgs.erase(strArg); + mapMultiArgs.erase(strArg); } static const int screenWidth = 79; @@ -693,7 +696,7 @@ fs::path GetConfigFile(const std::string& confPath) return pathConfigFile; } -void ReadConfigFile(const std::string& confPath) +void ArgsManager::ReadConfigFile(const std::string& confPath) { fs::ifstream streamConfig(GetConfigFile(confPath)); if (!streamConfig.good()){ @@ -717,7 +720,7 @@ void ReadConfigFile(const std::string& confPath) InterpretNegativeSetting(strKey, strValue); if (mapArgs.count(strKey) == 0) mapArgs[strKey] = strValue; - _mapMultiArgs[strKey].push_back(strValue); + mapMultiArgs[strKey].push_back(strValue); } } // If datadir is changed in .conf file: diff --git a/src/util.h b/src/util.h index 5b4d2df2e3fa..61641d508b5e 100644 --- a/src/util.h +++ b/src/util.h @@ -17,6 +17,7 @@ #include "compat.h" #include "fs.h" +#include "sync.h" #include "tinyformat.h" #include "utiltime.h" #include "amount.h" @@ -62,7 +63,6 @@ class CTranslationInterface boost::signals2::signal Translate; }; -extern const std::unordered_map >& mapMultiArgs; extern bool fPrintToConsole; extern bool fPrintToDebugLog; @@ -201,7 +201,6 @@ bool error(const char* fmt, const Args&... args) } void PrintExceptionContinue(const std::exception_ptr pex, const char* pszThread); -void ParseParameters(int argc, const char*const argv[]); void FileCommit(FILE *file); bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); @@ -217,7 +216,6 @@ fs::path GetConfigFile(const std::string& confPath); fs::path GetPidFile(); void CreatePidFile(const fs::path &path, pid_t pid); #endif -void ReadConfigFile(const std::string& confPath); #ifdef WIN32 fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif @@ -234,6 +232,16 @@ inline bool IsSwitchChar(char c) #endif } +class ArgsManager +{ +protected: + CCriticalSection cs_args; + std::map mapArgs; + std::map > mapMultiArgs; +public: + void ParseParameters(int argc, const char*const argv[]); + void ReadConfigFile(const std::string& confPath); + std::vector GetArgs(const std::string& strArg); /** * Return true if the given argument has been manually set * @@ -291,6 +299,65 @@ bool SoftSetBoolArg(const std::string& strArg, bool fValue); void ForceSetArg(const std::string& strArg, const std::string& strValue); void ForceSetMultiArgs(const std::string& strArg, const std::vector& values); void ForceRemoveArg(const std::string& strArg); +}; + +extern ArgsManager gArgs; + +// wrappers using the global ArgsManager: +static inline void ParseParameters(int argc, const char*const argv[]) +{ + gArgs.ParseParameters(argc, argv); +} + +static inline void ReadConfigFile(const std::string& confPath) +{ + gArgs.ReadConfigFile(confPath); +} + +static inline bool SoftSetArg(const std::string& strArg, const std::string& strValue) +{ + return gArgs.SoftSetArg(strArg, strValue); +} + +static inline void ForceSetArg(const std::string& strArg, const std::string& strValue) +{ + gArgs.ForceSetArg(strArg, strValue); +} + +static inline bool IsArgSet(const std::string& strArg) +{ + return gArgs.IsArgSet(strArg); +} + +static inline std::string GetArg(const std::string& strArg, const std::string& strDefault) +{ + return gArgs.GetArg(strArg, strDefault); +} + +static inline int64_t GetArg(const std::string& strArg, int64_t nDefault) +{ + return gArgs.GetArg(strArg, nDefault); +} + +static inline bool GetBoolArg(const std::string& strArg, bool fDefault) +{ + return gArgs.GetBoolArg(strArg, fDefault); +} + +static inline bool SoftSetBoolArg(const std::string& strArg, bool fValue) +{ + return gArgs.SoftSetBoolArg(strArg, fValue); +} + +static inline void ForceSetMultiArgs(const std::string& strArg, const std::vector& values) +{ + gArgs.ForceSetMultiArgs(strArg, values); +} + +static inline void ForceRemoveArg(const std::string& strArg) +{ + gArgs.ForceRemoveArg(strArg); +} /** * Format a string to be used as group of options in help messages From c44dece4867ea2d7212489b63046ce1966c13a07 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 21 Jun 2019 13:52:23 +0200 Subject: [PATCH 246/987] Disable DIP3 in multiple tests --- test/functional/assumevalid.py | 6 +++--- test/functional/bip65-cltv-p2p.py | 2 +- test/functional/bip9-softforks.py | 2 +- test/functional/bipdersig-p2p.py | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index 8e301c437922..ed2a2cbc0608 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -63,7 +63,7 @@ def setup_network(self): # Start node0. We don't start the other nodes yet since # we need to pre-mine a block with an invalid transaction # signature so we can pass in the block hash as assumevalid. - self.nodes = [start_node(0, self.options.tmpdir)] + self.nodes = [start_node(0, self.options.tmpdir, ["-dip3params=9000:9000"])] def send_blocks_until_disconnected(self, node): """Keep sending blocks to the node until we're disconnected.""" @@ -163,14 +163,14 @@ def run_test(self): # Start node1 and node2 with assumevalid so they accept a block with a bad signature. self.nodes.append(start_node(1, self.options.tmpdir, - ["-assumevalid=" + hex(block102.sha256)])) + ["-assumevalid=" + hex(block102.sha256), "-dip3params=9000:9000"])) node1 = BaseNode() # connects to node1 connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], node1)) node1.add_connection(connections[1]) node1.wait_for_verack() self.nodes.append(start_node(2, self.options.tmpdir, - ["-assumevalid=" + hex(block102.sha256)])) + ["-assumevalid=" + hex(block102.sha256), "-dip3params=9000:9000"])) node2 = BaseNode() # connects to node2 connections.append(NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], node2)) node2.add_connection(connections[2]) diff --git a/test/functional/bip65-cltv-p2p.py b/test/functional/bip65-cltv-p2p.py index 7a4f43280bd1..935b6522b631 100755 --- a/test/functional/bip65-cltv-p2p.py +++ b/test/functional/bip65-cltv-p2p.py @@ -38,7 +38,7 @@ class BIP65Test(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=3']] + self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=3', '-dip3params=9000:9000']] def run_test(self): test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index da7d1efa5dcc..e5ec1b31ce88 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -31,7 +31,7 @@ class BIP9SoftForksTest(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 - self.extra_args = [['-whitelist=127.0.0.1']] + self.extra_args = [['-whitelist=127.0.0.1', '-dip3params=9000:9000']] def run_test(self): self.test = TestManager(self, self.options.tmpdir) diff --git a/test/functional/bipdersig-p2p.py b/test/functional/bipdersig-p2p.py index b4b352dac62b..450c48328418 100755 --- a/test/functional/bipdersig-p2p.py +++ b/test/functional/bipdersig-p2p.py @@ -45,6 +45,7 @@ class BIP66Test(ComparisonTestFramework): def __init__(self): super().__init__() self.num_nodes = 1 + self.extra_args = [['-dip3params=9000:9000']] def run_test(self): test = TestManager(self, self.options.tmpdir) From c2ac477a117afc6fcd895d8b2c17f9ffbe254c26 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 21 Jun 2019 13:55:53 +0200 Subject: [PATCH 247/987] Use 4x as much headers in assumevalid.py Dash has only 1/4 of block time compared to Bitcoin, which requires 4 times the amount of headers so that the assumevalid check in ConnectBlock results in skipping of script checks. Using so many headers now causes block time validation to fail (too far in the future), so we need to adjust mock time as well. --- test/functional/assumevalid.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index ed2a2cbc0608..777bdf238c15 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -45,7 +45,8 @@ msg_headers) from test_framework.script import (CScript, OP_TRUE) from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import (start_node, p2p_port, assert_equal) +from test_framework.util import (start_node, p2p_port, assert_equal, get_mocktime, set_mocktime, set_node_times) + class BaseNode(NodeConnCB): def send_header_for_blocks(self, new_blocks): @@ -151,8 +152,8 @@ def run_test(self): self.block_time += 1 height += 1 - # Bury the assumed valid block 2100 deep - for i in range(2100): + # Bury the assumed valid block 8400 deep (Dash needs 4x as much blocks to allow -assumevalid to work) + for i in range(8400): block = create_block(self.tip, create_coinbase(height), self.block_time) block.nVersion = 4 block.solve() @@ -176,11 +177,21 @@ def run_test(self): node2.add_connection(connections[2]) node2.wait_for_verack() - # send header lists to all three nodes + # Make sure nodes actually accept the many headers + set_mocktime(self.block_time) + set_node_times(self.nodes, get_mocktime()) + + # send header lists to all three nodes. + # node0 does not need to receive all headers + # node1 must receive all headers as otherwise assumevalid is ignored in ConnectBlock + # node2 should NOT receive all headers to force skipping of the assumevalid check in ConnectBlock node0.send_header_for_blocks(self.blocks[0:2000]) node0.send_header_for_blocks(self.blocks[2000:]) node1.send_header_for_blocks(self.blocks[0:2000]) - node1.send_header_for_blocks(self.blocks[2000:]) + node1.send_header_for_blocks(self.blocks[2000:4000]) + node1.send_header_for_blocks(self.blocks[4000:6000]) + node1.send_header_for_blocks(self.blocks[6000:8000]) + node1.send_header_for_blocks(self.blocks[8000:]) node2.send_header_for_blocks(self.blocks[0:200]) # Send blocks to node0. Block 102 will be rejected. From d03bc6d023459166ba74e031b10f372a8439d534 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 21 Jun 2019 13:56:54 +0200 Subject: [PATCH 248/987] No need to send so many headers to node0 We're only interested in node0 processing up to block 102, so we don't need so many of the headers. --- test/functional/assumevalid.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index 777bdf238c15..1336a702f202 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -186,7 +186,6 @@ def run_test(self): # node1 must receive all headers as otherwise assumevalid is ignored in ConnectBlock # node2 should NOT receive all headers to force skipping of the assumevalid check in ConnectBlock node0.send_header_for_blocks(self.blocks[0:2000]) - node0.send_header_for_blocks(self.blocks[2000:]) node1.send_header_for_blocks(self.blocks[0:2000]) node1.send_header_for_blocks(self.blocks[2000:4000]) node1.send_header_for_blocks(self.blocks[4000:6000]) From c77c4330c7dbec01f16641bdfd3969386c7fd0cd Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 21 Jun 2019 13:57:51 +0200 Subject: [PATCH 249/987] Send less blocks to node1 We only want to verify that assumevalid causes block 102 to be accepted even though it contains an invalid script, so there is no need to send more blocks. --- test/functional/assumevalid.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index 1336a702f202..4049add2c739 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -197,12 +197,12 @@ def run_test(self): self.send_blocks_until_disconnected(node0) self.assert_blockchain_height(self.nodes[0], 101) - # Send all blocks to node1. All blocks will be accepted. - for i in range(2202): + # Send 200 blocks to node1. All blocks, including block 102, will be accepted. + for i in range(200): node1.send_message(msg_block(self.blocks[i])) - # Syncing 2200 blocks can take a while on slow systems. Give it plenty of time to sync. + # Syncing so many blocks can take a while on slow systems. Give it plenty of time to sync. node1.sync_with_ping(120) - assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202) + assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 200) # Send blocks to node2. Block 102 will be rejected. self.send_blocks_until_disconnected(node2) From a05d1630368bef18d84826c4bf394b29533ca274 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 21 Jun 2019 14:34:26 +0200 Subject: [PATCH 250/987] Remove unnecessary and forever-blocking wait_to_sync calls --- test/functional/bip9-softforks.py | 1 - test/functional/getblocktemplate_longpoll.py | 1 - test/functional/getblocktemplate_proposals.py | 1 - 3 files changed, 3 deletions(-) diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index e5ec1b31ce88..6e0d813fbc8a 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -74,7 +74,6 @@ def get_bip9_status(self, key): return info['bip9_softforks'][key] def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignature, bitno): - wait_to_sync(self.nodes[0]) assert_equal(self.get_bip9_status(bipName)['status'], 'defined') assert_equal(self.get_bip9_status(bipName)['since'], 0) # generate some coins for later diff --git a/test/functional/getblocktemplate_longpoll.py b/test/functional/getblocktemplate_longpoll.py index 8f25197d7802..bbe1dda5f734 100755 --- a/test/functional/getblocktemplate_longpoll.py +++ b/test/functional/getblocktemplate_longpoll.py @@ -30,7 +30,6 @@ def __init__(self): def run_test(self): self.log.info("Warning: this test will take about 70 seconds in the best case. Be patient.") - wait_to_sync(self.nodes[0]) self.nodes[0].generate(10) templat = self.nodes[0].getblocktemplate() longpollid = templat['longpollid'] diff --git a/test/functional/getblocktemplate_proposals.py b/test/functional/getblocktemplate_proposals.py index 4a6f5c283ad9..fca99c7df571 100755 --- a/test/functional/getblocktemplate_proposals.py +++ b/test/functional/getblocktemplate_proposals.py @@ -75,7 +75,6 @@ def __init__(self): def run_test(self): node = self.nodes[0] - wait_to_sync(node) node.generate(1) # Mine a block to leave initial block download tmpl = node.getblocktemplate() if 'coinbasetxn' not in tmpl: From a7f9f14d3623c5b94cc787c50d8d35f1bab7b636 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Fri, 21 Jun 2019 20:05:30 +0200 Subject: [PATCH 251/987] Give syncing in assumevalid.py more time --- test/functional/assumevalid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index 4049add2c739..7a1980e3f81e 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -201,7 +201,7 @@ def run_test(self): for i in range(200): node1.send_message(msg_block(self.blocks[i])) # Syncing so many blocks can take a while on slow systems. Give it plenty of time to sync. - node1.sync_with_ping(120) + node1.sync_with_ping(300) assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 200) # Send blocks to node2. Block 102 will be rejected. From 2b66fc664184bc33ccca7b4324903475d3597081 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Wed, 28 Jun 2017 18:09:54 +0200 Subject: [PATCH 252/987] Merge #10690: [qa] Bugfix: allow overriding extra_args in ComparisonTestFramework 4ed3653 [qa] Bugfix: allow overriding extra_args in ComparisonTestFramework (Suhas Daftuar) Tree-SHA512: d8f724b3324aad73a7b15cf87ff394e8d615bf3cd5a394d5715347d833f2ae9ac745a944202986866255eca5fc105ea06ab3abe12e168b67de34482f751c68e2 --- test/functional/test_framework/test_framework.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 8ab9afb99644..a01c1be5ed11 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -843,8 +843,10 @@ def add_options(self, parser): help="dashd binary to use for reference nodes (if any)") def setup_network(self): + extra_args = [['-whitelist=127.0.0.1']]*self.num_nodes + if hasattr(self, "extra_args"): + extra_args = self.extra_args self.nodes = self.start_nodes( - self.num_nodes, self.options.tmpdir, - extra_args=[['-whitelist=127.0.0.1']] * self.num_nodes, + self.num_nodes, self.options.tmpdir, extra_args, binary=[self.options.testbinary] + [self.options.refbinary]*(self.num_nodes-1)) From 38d37ae5ab746e4f2659c1b854c408cd855f31d7 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Sun, 23 Jun 2019 11:57:11 +0200 Subject: [PATCH 253/987] Don't check block indexes in assumevalid.py CheckBlockIndex slows down header processing a lot, so that this test even fails on Travis. --- test/functional/assumevalid.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index 7a1980e3f81e..eabace1024f2 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -64,7 +64,7 @@ def setup_network(self): # Start node0. We don't start the other nodes yet since # we need to pre-mine a block with an invalid transaction # signature so we can pass in the block hash as assumevalid. - self.nodes = [start_node(0, self.options.tmpdir, ["-dip3params=9000:9000"])] + self.nodes = [start_node(0, self.options.tmpdir, ["-dip3params=9000:9000", "-checkblockindex=0"])] def send_blocks_until_disconnected(self, node): """Keep sending blocks to the node until we're disconnected.""" @@ -164,14 +164,14 @@ def run_test(self): # Start node1 and node2 with assumevalid so they accept a block with a bad signature. self.nodes.append(start_node(1, self.options.tmpdir, - ["-assumevalid=" + hex(block102.sha256), "-dip3params=9000:9000"])) + ["-assumevalid=" + hex(block102.sha256), "-dip3params=9000:9000", "-checkblockindex=0"])) node1 = BaseNode() # connects to node1 connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], node1)) node1.add_connection(connections[1]) node1.wait_for_verack() self.nodes.append(start_node(2, self.options.tmpdir, - ["-assumevalid=" + hex(block102.sha256), "-dip3params=9000:9000"])) + ["-assumevalid=" + hex(block102.sha256), "-dip3params=9000:9000", "-checkblockindex=0"])) node2 = BaseNode() # connects to node2 connections.append(NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], node2)) node2.add_connection(connections[2]) From c7cafe5def027dc1f9a59c18ec1125a233dbb1b2 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 18 Sep 2017 16:02:24 +0200 Subject: [PATCH 254/987] Merge #11345: [tests] Check connectivity before sending in assumevalid.py e9e939108 [tests] Check connectivity before sending in assumevalid.py (John Newbery) Pull request description: assumevalid.py would try to send over a closed P2P connection in a loop, hitting the following failure many times: `TestFramework.mininode (ERROR): Cannot send message. No connection to node!` The test still passed, but this is a lot of noise in the test log. Just check that the connection is open before trying to send. Tree-SHA512: 6faf2ce5717de976fed1b5c863bc8d17e785928690f833d5bf175178f95d39f455635a844fe7e0dfdad83ae779dd45bc6e4ed89a9467d8482c5be73b55095c8d --- test/functional/assumevalid.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index eabace1024f2..7329c21ea358 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -69,6 +69,8 @@ def setup_network(self): def send_blocks_until_disconnected(self, node): """Keep sending blocks to the node until we're disconnected.""" for i in range(len(self.blocks)): + if not node.connection: + break try: node.send_message(msg_block(self.blocks[i])) except IOError as e: From ee7cebb2b08214ce5587d920517a8582ade3b672 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Sun, 23 Jun 2019 13:33:10 +0200 Subject: [PATCH 255/987] Temporary fix for race condition --- test/functional/assumevalid.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index 7329c21ea358..d0ca004666d8 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -73,8 +73,12 @@ def send_blocks_until_disconnected(self, node): break try: node.send_message(msg_block(self.blocks[i])) - except IOError as e: - assert str(e) == 'Not connected, no pushbuf' + # TODO There is a race condition between send_message and on_close which causes an AttributError on Travis + # We can reenable the correct exception handling and the assert when Bitcoin 0.16 mininode.py changes have been + # backported + #except IOError as e: + except: + #assert str(e) == 'Not connected, no pushbuf' break def assert_blockchain_height(self, node, height): From 3a0d4a1e649f0a0357b493d3b05f68cd64939117 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 15 May 2017 15:34:47 -0700 Subject: [PATCH 256/987] Merge #10380: [doc] Removing comments about dirty entries on txmempool 4f3782e [doc] Removing comments about dirty entries on txmempool (Simone Madeo) Tree-SHA512: 12ffad7237e2a8ec658cfcff263dad5a2220beadda48d67095df90c2f8ea55ffb6891d919698893b625965fb3069a05e7901fac6cceb3d1228e6833356408074 --- src/txmempool.h | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/txmempool.h b/src/txmempool.h index 08adff965879..c099fbef23d2 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -64,11 +64,6 @@ class CTxMemPool; * (nCountWithDescendants, nSizeWithDescendants, and nModFeesWithDescendants) for * all ancestors of the newly added transaction. * - * If updating the descendant state is skipped, we can mark the entry as - * "dirty", and set nSizeWithDescendants/nModFeesWithDescendants to equal nTxSize/ - * nFee+feeDelta. (This can potentially happen during a reorg, where we limit the - * amount of work we're willing to do to avoid consuming too much CPU.) - * */ class CTxMemPoolEntry @@ -87,9 +82,7 @@ class CTxMemPoolEntry // Information about descendants of this transaction that are in the // mempool; if we remove this transaction we must remove all of these - // descendants as well. if nCountWithDescendants is 0, treat this entry as - // dirty, and nSizeWithDescendants and nModFeesWithDescendants will not be - // correct. + // descendants as well. uint64_t nCountWithDescendants; //!< number of descendant transactions uint64_t nSizeWithDescendants; //!< ... and size CAmount nModFeesWithDescendants; //!< ... and total fees (all including us) @@ -119,7 +112,7 @@ class CTxMemPoolEntry size_t DynamicMemoryUsage() const { return nUsageSize; } const LockPoints& GetLockPoints() const { return lockPoints; } - // Adjusts the descendant state, if this entry is not dirty. + // Adjusts the descendant state. void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount); // Adjusts the ancestor state void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps); @@ -418,14 +411,6 @@ class SaltedTxidHasher * CalculateMemPoolAncestors() takes configurable limits that are designed to * prevent these calculations from being too CPU intensive. * - * Adding transactions from a disconnected block can be very time consuming, - * because we don't have a way to limit the number of in-mempool descendants. - * To bound CPU processing, we limit the amount of work we're willing to do - * to properly update the descendant information for a tx being added from - * a disconnected block. If we would exceed the limit, then we instead mark - * the entry as "dirty", and set the feerate for sorting purposes to be equal - * the feerate of the transaction without any descendants. - * */ class CTxMemPool { From 7918cae2f009db0e56e2abd115c6299be99db27f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 16 May 2017 08:06:26 +0200 Subject: [PATCH 257/987] Merge #10383: [logging] log system time and mock time 761392d [logging] log system time and mock time (John Newbery) Tree-SHA512: 0a4b3ad74bcac201be490fe12e4b45adeabc39030ac46f40e1aeb2a20b2f3963e4468e65798d8aaeca1818759cab55ff2b2aa214500aa11571492c3301dd31c1 --- src/util.cpp | 6 +++++- src/utiltime.cpp | 14 +++++--------- src/utiltime.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index cb2054a56124..0e51a46f8fe3 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -379,10 +379,14 @@ static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fSt int64_t nRealTimeMicros = GetTimeMicros(); strStamped = DateTimeStrFormat("(real %Y-%m-%d %H:%M:%S) ", nRealTimeMicros/1000000); } - int64_t nTimeMicros = GetLogTimeMicros(); + int64_t nTimeMicros = GetTimeMicros(); strStamped += DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nTimeMicros/1000000); if (fLogTimeMicros) strStamped += strprintf(".%06d", nTimeMicros%1000000); + int64_t mocktime = GetMockTime(); + if (mocktime) { + strStamped += " (mocktime: " + DateTimeStrFormat("%Y-%m-%d %H:%M:%S", mocktime) + ")"; + } strStamped += ' ' + str; } else strStamped = str; diff --git a/src/utiltime.cpp b/src/utiltime.cpp index eb866924fe3f..e18c6ebfd2ce 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -37,6 +37,11 @@ bool IsMockTime() return nMockTime != 0; } +int64_t GetMockTime() +{ + return nMockTime.load(std::memory_order_relaxed); +} + int64_t GetTimeMillis() { int64_t now = (boost::posix_time::microsec_clock::universal_time() - @@ -58,15 +63,6 @@ int64_t GetSystemTimeInSeconds() return GetTimeMicros()/1000000; } -/** Return a time useful for the debug log */ -int64_t GetLogTimeMicros() -{ - int64_t mocktime = nMockTime.load(std::memory_order_relaxed); - if (mocktime) return mocktime*1000000; - - return GetTimeMicros(); -} - void MilliSleep(int64_t n) { diff --git a/src/utiltime.h b/src/utiltime.h index 76c667339965..b4dc3b5dfa2e 100644 --- a/src/utiltime.h +++ b/src/utiltime.h @@ -23,9 +23,9 @@ int64_t GetTime(); int64_t GetTimeMillis(); int64_t GetTimeMicros(); int64_t GetSystemTimeInSeconds(); // Like GetTime(), but not mockable -int64_t GetLogTimeMicros(); void SetMockTime(int64_t nMockTimeIn); bool IsMockTime(); +int64_t GetMockTime(); void MilliSleep(int64_t n); std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime); From f2ee6f1aa5059b025622b1997617c4e429351e7b Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Tue, 16 May 2017 08:54:29 +0200 Subject: [PATCH 258/987] Merge #10362: [GUI] Add OSX keystroke to RPCConsole info 012fa9b99 Add OSX keystroke to clear RPCConsole (Spencer Lievens) Tree-SHA512: 124e9567d633fd80ab200e53b34c821947111ebb6ebd0b2ba3feacdbe2b6ab59ab447b87473f36d221d4189d92df6d53e34a8486aacaa8eaa4d9e413db01b11f --- src/qt/rpcconsole.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 13e2af93255a..53bebeace229 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -821,8 +821,14 @@ void RPCConsole::clear(bool clearHistory) ).arg(fixedFontInfo.family(), QString("%1pt").arg(consoleFontSize)) ); +#ifdef Q_OS_MAC + QString clsKey = "(⌘)-L"; +#else + QString clsKey = "Ctrl-L"; +#endif + message(CMD_REPLY, (tr("Welcome to the %1 RPC console.").arg(tr(PACKAGE_NAME)) + "
" + - tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" + + tr("Use up and down arrows to navigate history, and %1 to clear screen.").arg(""+clsKey+"") + "
" + tr("Type help for an overview of available commands.")) + "
" + tr("WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramification of a command.") + From c4bd31a4e46040eed38c4d07c6de0ee36d43b217 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 16 May 2017 12:12:58 +0200 Subject: [PATCH 259/987] Merge #10404: doc: Add logging to FinalizeNode() 1530bfc Add logging to FinalizeNode() (Suhas Daftuar) Tree-SHA512: 34bd950eb7830f378d069229c24122e97db68435b313f0de2c8772c2feefdc6db5f4d1f43eeade237ffe91cdef0f1cfe3232e1a37c561a65767f4527b2e2e370 --- src/net_processing.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index d159917e22f3..9ae0bce86cb1 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -342,6 +342,7 @@ void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) { assert(nPreferredDownload == 0); assert(nPeersWithValidatedDownloads == 0); } + LogPrint(BCLog::NET, "Cleared nodestate for peer=%d\n", nodeid); } // Requires cs_main. From 4dda3815629d44bbfd12e6cdbb6f05f3ae8edc1d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 17 May 2017 08:11:46 +0200 Subject: [PATCH 260/987] Merge #10374: qa: Warn when specified test is not found fac79e4 qa: Warn when specified test is not found (MarcoFalke) Tree-SHA512: d11ecdde275309b12e23155f6cd8e26c99217436b5094a70dd51b95ae7688754227628dd9a801eb6a52ff3ebea4420938e2fc8e9dc9cd77a4dd5c28d2b822354 --- test/README.md | 2 +- test/functional/test_runner.py | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/test/README.md b/test/README.md index dd258dd08698..1586913d97f7 100644 --- a/test/README.md +++ b/test/README.md @@ -34,7 +34,7 @@ You can run any single test by calling test/functional/test_runner.py -Or you can run any combination of tests by calling +Or you can run any combination (incl. duplicates) of tests by calling test/functional/test_runner.py ... diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index a07401db8999..c58d3fe7fee7 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -177,7 +177,7 @@ def main(): Help text and arguments for individual test script:''', formatter_class=argparse.RawTextHelpFormatter) parser.add_argument('--coverage', action='store_true', help='generate a basic coverage report for the RPC interface') - parser.add_argument('--exclude', '-x', help='specify a comma-seperated-list of scripts to exclude. Do not include the .py extension in the name.') + parser.add_argument('--exclude', '-x', help='specify a comma-seperated-list of scripts to exclude.') parser.add_argument('--extended', action='store_true', help='run the extended test suite in addition to the basic tests') parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).') parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit') @@ -186,8 +186,8 @@ def main(): parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.') args, unknown_args = parser.parse_known_args() - # Create a set to store arguments and create the passon string - tests = set(arg for arg in unknown_args if arg[:2] != "--") + # args to be passed on always start with two dashes; tests are the remaining unknown args + tests = [arg for arg in unknown_args if arg[:2] != "--"] passon_args = [arg for arg in unknown_args if arg[:2] == "--"] # Read config generated by configure. @@ -220,8 +220,13 @@ def main(): if tests: # Individual tests have been specified. Run specified tests that exist # in the ALL_SCRIPTS list. Accept the name with or without .py extension. - test_list = [t for t in ALL_SCRIPTS if - (t in tests or re.sub(".py$", "", t) in tests)] + tests = [re.sub("\.py$", "", t) + ".py" for t in tests] + test_list = [] + for t in tests: + if t in ALL_SCRIPTS: + test_list.append(t) + else: + print("{}WARNING!{} Test '{}' not found in full test list.".format(BOLD[1], BOLD[0], t)) else: # No individual tests have been specified. # Run all base tests, and optionally run extended tests. @@ -233,9 +238,12 @@ def main(): # Remove the test cases that the user has explicitly asked to exclude. if args.exclude: - for exclude_test in args.exclude.split(','): - if exclude_test + ".py" in test_list: - test_list.remove(exclude_test + ".py") + tests_excl = [re.sub("\.py$", "", t) + ".py" for t in args.exclude.split(',')] + for exclude_test in tests_excl: + if exclude_test in test_list: + test_list.remove(exclude_test) + else: + print("{}WARNING!{} Test '{}' not found in current test list.".format(BOLD[1], BOLD[0], exclude_test)) if not test_list: print("No valid test scripts specified. Check that your test is in one " From 23daebec7eeb28d31f8e4cb059f8e541c0670a89 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 17 May 2017 10:50:39 +0200 Subject: [PATCH 261/987] Merge #10405: tests: Correct testcase in script_tests.json for large number OP_EQUAL 2f84cf6 tests: Correct testcase in script_tests.json for large number OP_EQUAL (Wladimir J. van der Laan) Tree-SHA512: 3a4d33c7d65ea40f25e2f5f2dfab8b0262cac8a7c33698eef8332ca5ec4a6f88f73fc51441892b49ffa85660be5037644430585f2eab76e257d544f9c2271ab7 --- src/test/data/script_tests.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 3fcc2b9590a1..3631ce3d5d86 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -349,7 +349,7 @@ ["2147483647", "0x04 0xFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], ["2147483648", "0x05 0x0000008000 EQUAL", "P2SH,STRICTENC", "OK"], ["549755813887", "0x05 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], -["549755813888", "0x06 0xFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], +["549755813888", "0x06 0x000000008000 EQUAL", "P2SH,STRICTENC", "OK"], ["9223372036854775807", "0x08 0xFFFFFFFFFFFFFF7F EQUAL", "P2SH,STRICTENC", "OK"], ["-1", "0x01 0x81 EQUAL", "P2SH,STRICTENC", "OK", "Numbers are little-endian with the MSB being a sign bit"], ["-127", "0x01 0xFF EQUAL", "P2SH,STRICTENC", "OK"], From d84660729ec95d4525e879b7797e7b6dc242bc3e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 17 May 2017 11:06:49 +0200 Subject: [PATCH 262/987] Merge #7522: Bugfix: Only use git for build info if the repository is actually the right one ed1fcdc Bugfix: Detect genbuild.sh in repo correctly (Luke Dashjr) e98e3dd Bugfix: Only use git for build info if the repository is actually the right one (Luke Dashjr) Tree-SHA512: 510d7ec8cfeff4e8e0c7ac53631eb32c7acaada7017e7f8cc2e6f60d86afe1cd131870582e01022f961c85a783a130bcb8fef971f8b110070c9c02afda020726 --- contrib/gitian-descriptors/gitian-linux.yml | 1 + contrib/gitian-descriptors/gitian-osx.yml | 1 + contrib/gitian-descriptors/gitian-win.yml | 1 + share/genbuild.sh | 6 +++++- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index 6e8203be8226..aa5508c1bad3 100755 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -161,6 +161,7 @@ script: | export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host + export GIT_DIR="$PWD/.git" ./autogen.sh CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ make dist diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index 2995b31939f1..ab5b5d9b6877 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -120,6 +120,7 @@ script: | export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host + export GIT_DIR="$PWD/.git" ./autogen.sh CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ make dist diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index ee1a17149802..ff38be782abc 100755 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -149,6 +149,7 @@ script: | export PATH=${WRAP_DIR}:${PATH} # Create the release tarball using (arbitrarily) the first host + export GIT_DIR="$PWD/.git" ./autogen.sh CONFIG_SITE=${BASEPREFIX}/`echo "${HOSTS}" | awk '{print $1;}'`/share/config.site ./configure --prefix=/ make dist diff --git a/share/genbuild.sh b/share/genbuild.sh index eecac4bd00b9..32ef2a5755aa 100755 --- a/share/genbuild.sh +++ b/share/genbuild.sh @@ -17,9 +17,13 @@ else exit 1 fi +git_check_in_repo() { + ! { git status --porcelain -uall --ignored "$@" 2>/dev/null || echo '??'; } | grep -q '?' +} + DESC="" SUFFIX="" -if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then +if [ "${BITCOIN_GENBUILD_NO_GIT}" != "1" -a -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] && git_check_in_repo share/genbuild.sh; then # clean 'dirty' status of touched files that haven't been modified git diff >/dev/null 2>/dev/null From ad177ba6667dea9fd9d194abdc2ad81998a37260 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 17 May 2017 11:12:25 +0200 Subject: [PATCH 263/987] Merge #10319: Remove unused argument from MarkBlockAsInFlight(...) 6345f0b Remove unused argument from MarkBlockAsInFlight(...) (practicalswift) Tree-SHA512: c07616aac1a2e00d269ffd62861bb0fe3addc60c7a601ec4f9c212727697cf82d41d237cce8e043df02b7733d553bd99d9c999ebb299d376dbc63483ce182219 --- src/net_processing.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 9ae0bce86cb1..84328ba46b22 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -373,7 +373,7 @@ bool MarkBlockAsReceived(const uint256& hash) { // Requires cs_main. // returns false, still setting pit, if the block was already in flight from the same peer // pit will only be valid as long as the same cs_main lock is being held -bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const Consensus::Params& consensusParams, const CBlockIndex *pindex = NULL, std::list::iterator **pit = NULL) { +bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex *pindex = NULL, std::list::iterator **pit = NULL) { CNodeState *state = State(nodeid); assert(state != NULL); @@ -2440,7 +2440,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if ((!fAlreadyInFlight && nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) || (fAlreadyInFlight && blockInFlightIt->second.first == pfrom->GetId())) { std::list::iterator *queuedBlockIt = NULL; - if (!MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex, &queuedBlockIt)) { + if (!MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), pindex, &queuedBlockIt)) { if (!(*queuedBlockIt)->partialBlock) (*queuedBlockIt)->partialBlock.reset(new PartiallyDownloadedBlock(&mempool)); else { @@ -2742,7 +2742,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr break; } vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); - MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), chainparams.GetConsensus(), pindex); + MarkBlockAsInFlight(pfrom->GetId(), pindex->GetBlockHash(), pindex); LogPrint(BCLog::NET, "Requesting block %s from peer=%d\n", pindex->GetBlockHash().ToString(), pfrom->GetId()); } @@ -3675,7 +3675,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams); BOOST_FOREACH(const CBlockIndex *pindex, vToDownload) { vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); - MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), consensusParams, pindex); + MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), pindex); LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), pindex->nHeight, pto->GetId()); } From 6b548bf37ab9a8810481821a9046eb292a39a23d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 17 May 2017 11:18:09 +0200 Subject: [PATCH 264/987] Merge #10388: Output line to debug.log when IsInitialBlockDownload latches to false 65d484a Output line to debug.log when IsInitialBlockDownload latches to false (Alex Morcos) Tree-SHA512: 8b9d1377167a78ea55afc4582c8b9305c8b0fe56063a25920e9d45ea9335470314e3cfdc92e78b803d304476fa4c19b228fea1758bbeadd20c719006d814b5f2 --- src/validation.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/validation.cpp b/src/validation.cpp index 042b08d9e9bc..9a6502d9794e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1198,6 +1198,7 @@ bool IsInitialBlockDownload() return true; if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) return true; + LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); latchToFalse.store(true, std::memory_order_relaxed); return false; } From 2e050ea744dcc922f925a177aeafc14a396068ee Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 17 May 2017 17:17:51 -0700 Subject: [PATCH 265/987] Merge #10395: Replace boost::function with std::function (C++11) 1b936f5 Replace boost::function with std::function (C++11) (practicalswift) Tree-SHA512: c4faec8cf3f801842010976115681f68ffa08fbc97ba50b22e95c936840f47e1b3bd8d7fd2f5b4e094b5a46bf3d29fc90b69d975a99e77322c0d19f8a00d53d3 --- src/bench/bench.cpp | 1 + src/bench/bench.h | 5 +++-- src/httprpc.cpp | 4 ++-- src/init.cpp | 1 - src/qt/rpcconsole.cpp | 12 ++++++------ src/rpc/server.cpp | 8 ++++---- src/rpc/server.h | 12 +++++------- src/scheduler.h | 4 ++-- src/torcontrol.cpp | 9 ++++----- src/txdb.cpp | 2 +- src/txdb.h | 4 +--- 11 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp index a9c5571e4530..e5fa66890720 100644 --- a/src/bench/bench.cpp +++ b/src/bench/bench.cpp @@ -5,6 +5,7 @@ #include "bench.h" #include "perf.h" +#include #include #include #include diff --git a/src/bench/bench.h b/src/bench/bench.h index 5a050a746aa7..fcde850de03c 100644 --- a/src/bench/bench.h +++ b/src/bench/bench.h @@ -5,10 +5,11 @@ #ifndef BITCOIN_BENCH_BENCH_H #define BITCOIN_BENCH_BENCH_H +#include +#include #include #include -#include #include #include @@ -59,7 +60,7 @@ namespace benchmark { bool KeepRunning(); }; - typedef boost::function BenchFunction; + typedef std::function BenchFunction; class BenchRunner { diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 7fe821328593..df2fb9aae7f4 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -30,7 +30,7 @@ static const char* WWW_AUTH_HEADER_DATA = "Basic realm=\"jsonrpc\""; class HTTPRPCTimer : public RPCTimerBase { public: - HTTPRPCTimer(struct event_base* eventBase, boost::function& func, int64_t millis) : + HTTPRPCTimer(struct event_base* eventBase, std::function& func, int64_t millis) : ev(eventBase, false, func) { struct timeval tv; @@ -52,7 +52,7 @@ class HTTPRPCTimerInterface : public RPCTimerInterface { return "HTTP"; } - RPCTimerBase* NewTimer(boost::function& func, int64_t millis) override + RPCTimerBase* NewTimer(std::function& func, int64_t millis) override { return new HTTPRPCTimer(base, func, millis); } diff --git a/src/init.cpp b/src/init.cpp index 4e1b639d8e60..86e2ce4ee76b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -88,7 +88,6 @@ #include #include #include -#include #include #include #include diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 53bebeace229..d99530d53859 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -108,7 +108,7 @@ class QtRPCTimerBase: public QObject, public RPCTimerBase { Q_OBJECT public: - QtRPCTimerBase(boost::function& _func, int64_t millis): + QtRPCTimerBase(std::function& _func, int64_t millis): func(_func) { timer.setSingleShot(true); @@ -120,7 +120,7 @@ private Q_SLOTS: void timeout() { func(); } private: QTimer timer; - boost::function func; + std::function func; }; class QtRPCTimerInterface: public RPCTimerInterface @@ -128,7 +128,7 @@ class QtRPCTimerInterface: public RPCTimerInterface public: ~QtRPCTimerInterface() {} const char *Name() override { return "Qt"; } - RPCTimerBase* NewTimer(boost::function& func, int64_t millis) override + RPCTimerBase* NewTimer(std::function& func, int64_t millis) override { return new QtRPCTimerBase(func, millis); } @@ -452,7 +452,7 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) : connect(ui->fontBiggerButton, SIGNAL(clicked()), this, SLOT(fontBigger())); connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller())); connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear())); - + // Wallet Repair Buttons // connect(ui->btn_salvagewallet, SIGNAL(clicked()), this, SLOT(walletSalvage())); // Disable salvage option in GUI, it's way too powerful and can lead to funds loss @@ -774,7 +774,7 @@ void RPCConsole::buildParameterlist(QString arg) args.removeAll(ZAPTXES2); args.removeAll(UPGRADEWALLET); args.removeAll(REINDEX); - + // Append repair parameter to command line. args.append(arg); @@ -797,7 +797,7 @@ void RPCConsole::clear(bool clearHistory) // (when using width/height on an img, Qt uses nearest instead of linear interpolation) QString iconPath = ":/icons/" + GUIUtil::getThemeName() + "/"; QString iconName = ""; - + for(int i=0; ICON_MAPPING[i].url; ++i) { iconName = ICON_MAPPING[i].source; diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 3e1f8c1824fe..7033d930f987 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -46,17 +46,17 @@ static struct CRPCSignals boost::signals2::signal PreCommand; } g_rpcSignals; -void RPCServer::OnStarted(boost::function slot) +void RPCServer::OnStarted(std::function slot) { g_rpcSignals.Started.connect(slot); } -void RPCServer::OnStopped(boost::function slot) +void RPCServer::OnStopped(std::function slot) { g_rpcSignals.Stopped.connect(slot); } -void RPCServer::OnPreCommand(boost::function slot) +void RPCServer::OnPreCommand(std::function slot) { g_rpcSignals.PreCommand.connect(boost::bind(slot, _1)); } @@ -595,7 +595,7 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface) timerInterface = NULL; } -void RPCRunLater(const std::string& name, boost::function func, int64_t nSeconds) +void RPCRunLater(const std::string& name, std::function func, int64_t nSeconds) { if (!timerInterface) throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC"); diff --git a/src/rpc/server.h b/src/rpc/server.h index d90846c34223..98e2bddbe5db 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -15,17 +15,15 @@ #include #include -#include - #include class CRPCCommand; namespace RPCServer { - void OnStarted(boost::function slot); - void OnStopped(boost::function slot); - void OnPreCommand(boost::function slot); + void OnStarted(std::function slot); + void OnStopped(std::function slot); + void OnPreCommand(std::function slot); } class CBlockIndex; @@ -113,7 +111,7 @@ class RPCTimerInterface * This is needed to cope with the case in which there is no HTTP server, but * only GUI RPC console, and to break the dependency of pcserver on httprpc. */ - virtual RPCTimerBase* NewTimer(boost::function& func, int64_t millis) = 0; + virtual RPCTimerBase* NewTimer(std::function& func, int64_t millis) = 0; }; /** Set the factory function for timers */ @@ -127,7 +125,7 @@ void RPCUnsetTimerInterface(RPCTimerInterface *iface); * Run func nSeconds from now. * Overrides previous timer (if any). */ -void RPCRunLater(const std::string& name, boost::function func, int64_t nSeconds); +void RPCRunLater(const std::string& name, std::function func, int64_t nSeconds); typedef UniValue(*rpcfn_type)(const JSONRPCRequest& jsonRequest); diff --git a/src/scheduler.h b/src/scheduler.h index 613fc1653fdf..27412a15b465 100644 --- a/src/scheduler.h +++ b/src/scheduler.h @@ -7,8 +7,8 @@ // // NOTE: -// boost::thread / boost::function / boost::chrono should be ported to -// std::thread / std::function / std::chrono when we support C++11. +// boost::thread / boost::chrono should be ported to std::thread / std::chrono +// when we support C++11. // #include #include diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 91e087bdfc61..620eaac1bc29 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -73,8 +72,8 @@ class TorControlReply class TorControlConnection { public: - typedef boost::function ConnectionCB; - typedef boost::function ReplyHandlerCB; + typedef std::function ConnectionCB; + typedef std::function ReplyHandlerCB; /** Create a new TorControlConnection. */ @@ -105,9 +104,9 @@ class TorControlConnection boost::signals2::signal async_handler; private: /** Callback when ready for use */ - boost::function connected; + std::function connected; /** Callback when connection lost */ - boost::function disconnected; + std::function disconnected; /** Libevent event base */ struct event_base *base; /** Connection to control socket */ diff --git a/src/txdb.cpp b/src/txdb.cpp index 17596e414d04..944cfcaf1cd3 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -344,7 +344,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { return true; } -bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex) +bool CBlockTreeDB::LoadBlockIndexGuts(std::function insertBlockIndex) { std::unique_ptr pcursor(NewIterator()); diff --git a/src/txdb.h b/src/txdb.h index 9e7c5b699d0b..de3a00dceb3a 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -16,8 +16,6 @@ #include #include -#include - class CBlockIndex; class CCoinsViewDBCursor; class uint256; @@ -138,7 +136,7 @@ class CBlockTreeDB : public CDBWrapper bool ReadTimestampIndex(const unsigned int &high, const unsigned int &low, std::vector &vect); bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); - bool LoadBlockIndexGuts(boost::function insertBlockIndex); + bool LoadBlockIndexGuts(std::function insertBlockIndex); }; #endif // BITCOIN_TXDB_H From 64d4113e01dff16e766c131a249da8c9a45ecdf1 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 17 May 2017 17:26:54 -0700 Subject: [PATCH 266/987] Merge #10061: [net] Added SetSocketNoDelay() utility function ad415bc [net] Added SetSocketNoDelay() utility function (Thomas Snider) Tree-SHA512: c19e3c9910b3fc2ef86f2434f3e91d343e9cd9e2116153941de9789e2a6fc0389bffe762d21b55cda4a4b1de993afee0564c6946e65d05cef9e866b58896f9af --- src/net.cpp | 7 +------ src/netbase.cpp | 15 +++++++++------ src/netbase.h | 2 ++ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index d141708923c2..bb89fc422ed5 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1127,12 +1127,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { // According to the internet TCP_NODELAY is not carried into accepted sockets // on all platforms. Set it again here just to be sure. - int set = 1; -#ifdef WIN32 - setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int)); -#else - setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int)); -#endif + SetSocketNoDelay(hSocket); if (IsBanned(addr) && !whitelisted) { diff --git a/src/netbase.cpp b/src/netbase.cpp index 2739520b6b45..f16cb8f343e3 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -428,18 +428,14 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (hSocket == INVALID_SOCKET) return false; - int set = 1; #ifdef SO_NOSIGPIPE + int set = 1; // Different way of disabling SIGPIPE on BSD setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int)); #endif //Disable Nagle's algorithm -#ifdef WIN32 - setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int)); -#else - setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int)); -#endif + SetSocketNoDelay(hSocket); // Set to non-blocking if (!SetSocketNonBlocking(hSocket, true)) @@ -728,6 +724,13 @@ bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking) return true; } +bool SetSocketNoDelay(SOCKET& hSocket) +{ + int set = 1; + int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int)); + return rc == 0; +} + void InterruptSocks5(bool interrupt) { interruptSocks5Recv = interrupt; diff --git a/src/netbase.h b/src/netbase.h index 813dcd989c4c..221986cba39e 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -60,6 +60,8 @@ std::string NetworkErrorString(int err); bool CloseSocket(SOCKET& hSocket); /** Disable or enable blocking-mode for a socket */ bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking); +/** Set the TCP_NODELAY flag on a socket */ +bool SetSocketNoDelay(SOCKET& hSocket); /** * Convert milliseconds to a struct timeval for e.g. select. */ From 895c95cd909f2fd9e1069935246a78e8ba2c9c1f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 18 May 2017 10:08:56 +0200 Subject: [PATCH 267/987] Merge #9750: Bloomfilter: parameter variables made constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 64aa36e param variables made const (ロハン ダル) Tree-SHA512: 7c19f9e7dd574c8ce8a9468555f27196735b583efe349c1309c90e1e5d2949daf6891574b4bea7122d6c6aca0c7ee4a782fe3d24918d889f7bf89227084a51cd --- src/bloom.cpp | 8 ++++---- src/bloom.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/bloom.cpp b/src/bloom.cpp index 1807602d7197..3f7a49c9fe1d 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -23,7 +23,7 @@ #define LN2SQUARED 0.4804530139182014246671025263266649717305529515945455 #define LN2 0.6931471805599453094172321214581765680755001343602552 -CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweakIn, unsigned char nFlagsIn) : +CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn, unsigned char nFlagsIn) : /** * The ideal size for a bloom filter with a given number of elements and false positive rate is: * - nElements * log(fp rate) / ln(2)^2 @@ -44,7 +44,7 @@ CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int } // Private constructor used by CRollingBloomFilter -CBloomFilter::CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweakIn) : +CBloomFilter::CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweakIn) : vData((unsigned int)(-1 / LN2SQUARED * nElements * log(nFPRate)) / 8), isFull(false), isEmpty(true), @@ -130,7 +130,7 @@ void CBloomFilter::clear() isEmpty = true; } -void CBloomFilter::reset(unsigned int nNewTweak) +void CBloomFilter::reset(const unsigned int nNewTweak) { clear(); nTweak = nNewTweak; @@ -299,7 +299,7 @@ void CBloomFilter::UpdateEmptyFull() isEmpty = empty; } -CRollingBloomFilter::CRollingBloomFilter(unsigned int nElements, double fpRate) +CRollingBloomFilter::CRollingBloomFilter(const unsigned int nElements, const double fpRate) { double logFpRate = log(fpRate); /* The optimal number of hash functions is log(fpRate) / log(0.5), but diff --git a/src/bloom.h b/src/bloom.h index 8b6abec6bcc8..93eec47e0ba3 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -56,7 +56,7 @@ class CBloomFilter unsigned int Hash(unsigned int nHashNum, const std::vector& vDataToHash) const; // Private constructor for CRollingBloomFilter, no restrictions on size - CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak); + CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak); friend class CRollingBloomFilter; // Check matches for arbitrary script data elements @@ -73,7 +73,7 @@ class CBloomFilter * It should generally always be a random value (and is largely only exposed for unit testing) * nFlags should be one of the BLOOM_UPDATE_* enums (not _MASK) */ - CBloomFilter(unsigned int nElements, double nFPRate, unsigned int nTweak, unsigned char nFlagsIn); + CBloomFilter(const unsigned int nElements, const double nFPRate, const unsigned int nTweak, unsigned char nFlagsIn); CBloomFilter() : isFull(true), isEmpty(false), nHashFuncs(0), nTweak(0), nFlags(0) {} ADD_SERIALIZE_METHODS; @@ -96,7 +96,7 @@ class CBloomFilter bool contains(const uint160& hash) const; void clear(); - void reset(unsigned int nNewTweak); + void reset(const unsigned int nNewTweak); //! True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS //! (catch a filter which was just deserialized which was too big) @@ -129,7 +129,7 @@ class CRollingBloomFilter // A random bloom filter calls GetRand() at creation time. // Don't create global CRollingBloomFilter objects, as they may be // constructed before the randomizer is properly initialized. - CRollingBloomFilter(unsigned int nElements, double nFPRate); + CRollingBloomFilter(const unsigned int nElements, const double nFPRate); void insert(const std::vector& vKey); void insert(const uint256& hash); From 7ebe41b4b44600ff98acbe9943a34f5c8306e3e8 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 18 May 2017 19:58:34 +0200 Subject: [PATCH 268/987] Merge #10408: Net: Improvements to Tor control port parser 49a199b torcontrol: Handle escapes in Tor QuotedStrings (Jack Grigg) 0182a11 torcontrol: Log invalid parameters in Tor reply strings where meaningful (Jack Grigg) 0b6f40d torcontrol: Check for reading errors in ReadBinaryFile (Jack Grigg) d63677b torcontrol: Fix ParseTorReplyMapping (Jack Grigg) 29f3c20 torcontrol: Add unit tests for Tor reply parsers (Jack Grigg) d8e03c0 torcontrol: Improve comments (Jack Grigg) Tree-SHA512: aa3ce8072d20299b38c4ba9471af7fab1f5df096c237bf40a96ee9274a357f7366f95ced0cc80f8da1f22f6455a1a8e68bad9a5ff71817eef3397b6aefcbc7ae --- src/Makefile.test.include | 1 + src/test/torcontrol_tests.cpp | 199 ++++++++++++++++++++++++++++++++++ src/torcontrol.cpp | 82 ++++++++++++-- 3 files changed, 275 insertions(+), 7 deletions(-) create mode 100644 src/test/torcontrol_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index f3542319b6e3..61fdf60e4f6d 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -91,6 +91,7 @@ BITCOIN_TESTS =\ test/testutil.cpp \ test/testutil.h \ test/timedata_tests.cpp \ + test/torcontrol_tests.cpp \ test/transaction_tests.cpp \ test/txvalidationcache_tests.cpp \ test/versionbits_tests.cpp \ diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp new file mode 100644 index 000000000000..b7affaacde58 --- /dev/null +++ b/src/test/torcontrol_tests.cpp @@ -0,0 +1,199 @@ +// Copyright (c) 2017 The Zcash developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// +#include "test/test_bitcoin.h" +#include "torcontrol.cpp" + +#include + + +BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup) + +void CheckSplitTorReplyLine(std::string input, std::string command, std::string args) +{ + BOOST_TEST_MESSAGE(std::string("CheckSplitTorReplyLine(") + input + ")"); + auto ret = SplitTorReplyLine(input); + BOOST_CHECK_EQUAL(ret.first, command); + BOOST_CHECK_EQUAL(ret.second, args); +} + +BOOST_AUTO_TEST_CASE(util_SplitTorReplyLine) +{ + // Data we should receive during normal usage + CheckSplitTorReplyLine( + "PROTOCOLINFO PIVERSION", + "PROTOCOLINFO", "PIVERSION"); + CheckSplitTorReplyLine( + "AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"", + "AUTH", "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\""); + CheckSplitTorReplyLine( + "AUTH METHODS=NULL", + "AUTH", "METHODS=NULL"); + CheckSplitTorReplyLine( + "AUTH METHODS=HASHEDPASSWORD", + "AUTH", "METHODS=HASHEDPASSWORD"); + CheckSplitTorReplyLine( + "VERSION Tor=\"0.2.9.8 (git-a0df013ea241b026)\"", + "VERSION", "Tor=\"0.2.9.8 (git-a0df013ea241b026)\""); + CheckSplitTorReplyLine( + "AUTHCHALLENGE SERVERHASH=aaaa SERVERNONCE=bbbb", + "AUTHCHALLENGE", "SERVERHASH=aaaa SERVERNONCE=bbbb"); + + // Other valid inputs + CheckSplitTorReplyLine("COMMAND", "COMMAND", ""); + CheckSplitTorReplyLine("COMMAND SOME ARGS", "COMMAND", "SOME ARGS"); + + // These inputs are valid because PROTOCOLINFO accepts an OtherLine that is + // just an OptArguments, which enables multiple spaces to be present + // between the command and arguments. + CheckSplitTorReplyLine("COMMAND ARGS", "COMMAND", " ARGS"); + CheckSplitTorReplyLine("COMMAND EVEN+more ARGS", "COMMAND", " EVEN+more ARGS"); +} + +void CheckParseTorReplyMapping(std::string input, std::map expected) +{ + BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(") + input + ")"); + auto ret = ParseTorReplyMapping(input); + BOOST_CHECK_EQUAL(ret.size(), expected.size()); + auto r_it = ret.begin(); + auto e_it = expected.begin(); + while (r_it != ret.end() && e_it != expected.end()) { + BOOST_CHECK_EQUAL(r_it->first, e_it->first); + BOOST_CHECK_EQUAL(r_it->second, e_it->second); + r_it++; + e_it++; + } +} + +BOOST_AUTO_TEST_CASE(util_ParseTorReplyMapping) +{ + // Data we should receive during normal usage + CheckParseTorReplyMapping( + "METHODS=COOKIE,SAFECOOKIE COOKIEFILE=\"/home/x/.tor/control_auth_cookie\"", { + {"METHODS", "COOKIE,SAFECOOKIE"}, + {"COOKIEFILE", "/home/x/.tor/control_auth_cookie"}, + }); + CheckParseTorReplyMapping( + "METHODS=NULL", { + {"METHODS", "NULL"}, + }); + CheckParseTorReplyMapping( + "METHODS=HASHEDPASSWORD", { + {"METHODS", "HASHEDPASSWORD"}, + }); + CheckParseTorReplyMapping( + "Tor=\"0.2.9.8 (git-a0df013ea241b026)\"", { + {"Tor", "0.2.9.8 (git-a0df013ea241b026)"}, + }); + CheckParseTorReplyMapping( + "SERVERHASH=aaaa SERVERNONCE=bbbb", { + {"SERVERHASH", "aaaa"}, + {"SERVERNONCE", "bbbb"}, + }); + CheckParseTorReplyMapping( + "ServiceID=exampleonion1234", { + {"ServiceID", "exampleonion1234"}, + }); + CheckParseTorReplyMapping( + "PrivateKey=RSA1024:BLOB", { + {"PrivateKey", "RSA1024:BLOB"}, + }); + CheckParseTorReplyMapping( + "ClientAuth=bob:BLOB", { + {"ClientAuth", "bob:BLOB"}, + }); + + // Other valid inputs + CheckParseTorReplyMapping( + "Foo=Bar=Baz Spam=Eggs", { + {"Foo", "Bar=Baz"}, + {"Spam", "Eggs"}, + }); + CheckParseTorReplyMapping( + "Foo=\"Bar=Baz\"", { + {"Foo", "Bar=Baz"}, + }); + CheckParseTorReplyMapping( + "Foo=\"Bar Baz\"", { + {"Foo", "Bar Baz"}, + }); + + // Escapes + CheckParseTorReplyMapping( + "Foo=\"Bar\\ Baz\"", { + {"Foo", "Bar Baz"}, + }); + CheckParseTorReplyMapping( + "Foo=\"Bar\\Baz\"", { + {"Foo", "BarBaz"}, + }); + CheckParseTorReplyMapping( + "Foo=\"Bar\\@Baz\"", { + {"Foo", "Bar@Baz"}, + }); + CheckParseTorReplyMapping( + "Foo=\"Bar\\\"Baz\" Spam=\"\\\"Eggs\\\"\"", { + {"Foo", "Bar\"Baz"}, + {"Spam", "\"Eggs\""}, + }); + CheckParseTorReplyMapping( + "Foo=\"Bar\\\\Baz\"", { + {"Foo", "Bar\\Baz"}, + }); + + // C escapes + CheckParseTorReplyMapping( + "Foo=\"Bar\\nBaz\\t\" Spam=\"\\rEggs\" Octals=\"\\1a\\11\\17\\18\\81\\377\\378\\400\\2222\" Final=Check", { + {"Foo", "Bar\nBaz\t"}, + {"Spam", "\rEggs"}, + {"Octals", "\1a\11\17\1" "881\377\37" "8\40" "0\222" "2"}, + {"Final", "Check"}, + }); + CheckParseTorReplyMapping( + "Valid=Mapping Escaped=\"Escape\\\\\"", { + {"Valid", "Mapping"}, + {"Escaped", "Escape\\"}, + }); + CheckParseTorReplyMapping( + "Valid=Mapping Bare=\"Escape\\\"", {}); + CheckParseTorReplyMapping( + "OneOctal=\"OneEnd\\1\" TwoOctal=\"TwoEnd\\11\"", { + {"OneOctal", "OneEnd\1"}, + {"TwoOctal", "TwoEnd\11"}, + }); + + // Special handling for null case + // (needed because string comparison reads the null as end-of-string) + BOOST_TEST_MESSAGE(std::string("CheckParseTorReplyMapping(Null=\"\\0\")")); + auto ret = ParseTorReplyMapping("Null=\"\\0\""); + BOOST_CHECK_EQUAL(ret.size(), 1); + auto r_it = ret.begin(); + BOOST_CHECK_EQUAL(r_it->first, "Null"); + BOOST_CHECK_EQUAL(r_it->second.size(), 1); + BOOST_CHECK_EQUAL(r_it->second[0], '\0'); + + // A more complex valid grammar. PROTOCOLINFO accepts a VersionLine that + // takes a key=value pair followed by an OptArguments, making this valid. + // Because an OptArguments contains no semantic data, there is no point in + // parsing it. + CheckParseTorReplyMapping( + "SOME=args,here MORE optional=arguments here", { + {"SOME", "args,here"}, + }); + + // Inputs that are effectively invalid under the target grammar. + // PROTOCOLINFO accepts an OtherLine that is just an OptArguments, which + // would make these inputs valid. However, + // - This parser is never used in that situation, because the + // SplitTorReplyLine parser enables OtherLine to be skipped. + // - Even if these were valid, an OptArguments contains no semantic data, + // so there is no point in parsing it. + CheckParseTorReplyMapping("ARGS", {}); + CheckParseTorReplyMapping("MORE ARGS", {}); + CheckParseTorReplyMapping("MORE ARGS", {}); + CheckParseTorReplyMapping("EVEN more=ARGS", {}); + CheckParseTorReplyMapping("EVEN+more ARGS", {}); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 620eaac1bc29..3c6455f37126 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2015 The Bitcoin Core developers +// Copyright (c) 2017 The Zcash developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -249,6 +250,8 @@ bool TorControlConnection::Command(const std::string &cmd, const ReplyHandlerCB& /* Split reply line in the form 'AUTH METHODS=...' into a type * 'AUTH' and arguments 'METHODS=...'. + * Grammar is implicitly defined in https://spec.torproject.org/control-spec by + * the server reply formats for PROTOCOLINFO (S3.21) and AUTHCHALLENGE (S3.24). */ static std::pair SplitTorReplyLine(const std::string &s) { @@ -264,6 +267,10 @@ static std::pair SplitTorReplyLine(const std::string &s } /** Parse reply arguments in the form 'METHODS=COOKIE,SAFECOOKIE COOKIEFILE=".../control_auth_cookie"'. + * Returns a map of keys to values, or an empty map if there was an error. + * Grammar is implicitly defined in https://spec.torproject.org/control-spec by + * the server reply formats for PROTOCOLINFO (S3.21), AUTHCHALLENGE (S3.24), + * and ADD_ONION (S3.27). See also sections 2.1 and 2.3. */ static std::map ParseTorReplyMapping(const std::string &s) { @@ -271,28 +278,74 @@ static std::map ParseTorReplyMapping(const std::string size_t ptr=0; while (ptr < s.size()) { std::string key, value; - while (ptr < s.size() && s[ptr] != '=') { + while (ptr < s.size() && s[ptr] != '=' && s[ptr] != ' ') { key.push_back(s[ptr]); ++ptr; } if (ptr == s.size()) // unexpected end of line return std::map(); + if (s[ptr] == ' ') // The remaining string is an OptArguments + break; ++ptr; // skip '=' if (ptr < s.size() && s[ptr] == '"') { // Quoted string - ++ptr; // skip '=' + ++ptr; // skip opening '"' bool escape_next = false; - while (ptr < s.size() && (!escape_next && s[ptr] != '"')) { - escape_next = (s[ptr] == '\\'); + while (ptr < s.size() && (escape_next || s[ptr] != '"')) { + // Repeated backslashes must be interpreted as pairs + escape_next = (s[ptr] == '\\' && !escape_next); value.push_back(s[ptr]); ++ptr; } if (ptr == s.size()) // unexpected end of line return std::map(); ++ptr; // skip closing '"' - /* TODO: unescape value - according to the spec this depends on the - * context, some strings use C-LogPrintf style escape codes, some - * don't. So may be better handled at the call site. + /** + * Unescape value. Per https://spec.torproject.org/control-spec section 2.1.1: + * + * For future-proofing, controller implementors MAY use the following + * rules to be compatible with buggy Tor implementations and with + * future ones that implement the spec as intended: + * + * Read \n \t \r and \0 ... \377 as C escapes. + * Treat a backslash followed by any other character as that character. */ + std::string escaped_value; + for (size_t i = 0; i < value.size(); ++i) { + if (value[i] == '\\') { + // This will always be valid, because if the QuotedString + // ended in an odd number of backslashes, then the parser + // would already have returned above, due to a missing + // terminating double-quote. + ++i; + if (value[i] == 'n') { + escaped_value.push_back('\n'); + } else if (value[i] == 't') { + escaped_value.push_back('\t'); + } else if (value[i] == 'r') { + escaped_value.push_back('\r'); + } else if ('0' <= value[i] && value[i] <= '7') { + size_t j; + // Octal escape sequences have a limit of three octal digits, + // but terminate at the first character that is not a valid + // octal digit if encountered sooner. + for (j = 1; j < 3 && (i+j) < value.size() && '0' <= value[i+j] && value[i+j] <= '7'; ++j) {} + // Tor restricts first digit to 0-3 for three-digit octals. + // A leading digit of 4-7 would therefore be interpreted as + // a two-digit octal. + if (j == 3 && value[i] > '3') { + j--; + } + escaped_value.push_back(strtol(value.substr(i, j).c_str(), NULL, 8)); + // Account for automatic incrementing at loop end + i += j - 1; + } else { + escaped_value.push_back(value[i]); + } + } else { + escaped_value.push_back(value[i]); + } + } + value = escaped_value; } else { // Unquoted value. Note that values can contain '=' at will, just no spaces while (ptr < s.size() && s[ptr] != ' ') { value.push_back(s[ptr]); @@ -322,6 +375,10 @@ static std::pair ReadBinaryFile(const fs::path &filename, size char buffer[128]; size_t n; while ((n=fread(buffer, 1, sizeof(buffer), f)) > 0) { + // Check for reading errors so we don't return any data if we couldn't + // read the entire file (or up to maxsize) + if (ferror(f)) + return std::make_pair(false,""); retval.append(buffer, buffer+n); if (retval.size() > maxsize) break; @@ -438,6 +495,13 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe if ((i = m.find("PrivateKey")) != m.end()) private_key = i->second; } + if (service_id.empty()) { + LogPrintf("tor: Error parsing ADD_ONION parameters:\n"); + for (const std::string &s : reply.lines) { + LogPrintf(" %s\n", SanitizeString(s)); + } + return; + } service = LookupNumeric(std::string(service_id+".onion").c_str(), GetListenPort()); LogPrintf("tor: Got service ID %s, advertising service %s\n", service_id, service.ToString()); if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) { @@ -515,6 +579,10 @@ void TorController::authchallenge_cb(TorControlConnection& _conn, const TorContr std::pair l = SplitTorReplyLine(reply.lines[0]); if (l.first == "AUTHCHALLENGE") { std::map m = ParseTorReplyMapping(l.second); + if (m.empty()) { + LogPrintf("tor: Error parsing AUTHCHALLENGE parameters: %s\n", SanitizeString(l.second)); + return; + } std::vector serverHash = ParseHex(m["SERVERHASH"]); std::vector serverNonce = ParseHex(m["SERVERNONCE"]); LogPrint(BCLog::TOR, "tor: AUTHCHALLENGE ServerHash %s ServerNonce %s\n", HexStr(serverHash), HexStr(serverNonce)); From e32bbf40be15b746021db8a79fccfa2fea129b5f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 19 May 2017 15:49:19 +0200 Subject: [PATCH 269/987] Merge #10432: [Trivial] Add BITCOIN_FS_H endif footer in fs.h 2300a5e [Trivial] Add BITCOIN_FS_H endif footer in fs.h (Ahmad Kazi) Tree-SHA512: fd56c5c78c12db74baeef93186b59814ac626beeecfad5db852ab8eaad8e71f7f47d64590bcdd9052cc9e97f4531ba90c1f66f0f9e6517d2f956d622803111df --- src/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fs.h b/src/fs.h index 585cbf9c3825..abb4be254b8f 100644 --- a/src/fs.h +++ b/src/fs.h @@ -21,4 +21,4 @@ namespace fsbridge { FILE *freopen(const fs::path& p, const char *mode, FILE *stream); }; -#endif +#endif // BITCOIN_FS_H From 1f81ce12be8f755e44c645567e6dbf375e21daf7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 19 May 2017 15:51:11 +0200 Subject: [PATCH 270/987] Merge #10429: tests: fix spurious addrman test failure 6b51b0a tests: fix spurious addrman test failure (Cory Fields) Tree-SHA512: 3d41723b1a31ff459d950331ffea7f383e4ef6187990be6a634978bead0c29d7c096f68e7edb6d4dc56069c1fe8a6f12a6daf573cb1e542b15d000eaa54ad288 --- src/test/addrman_tests.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index ed690bcfdc2a..f55ec7513144 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -104,10 +104,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple) // Test: New table has one addr and we add a diff addr we should - // have two addrs. + // have at least one addr. + // Note that addrman's size cannot be tested reliably after insertion, as + // hash collisions may occur. But we can always be sure of at least one + // success. + CService addr2 = ResolveService("250.1.1.2", 8333); BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source)); - BOOST_CHECK_EQUAL(addrman.size(), 2); + BOOST_CHECK(addrman.size() >= 1); // Test: AddrMan::Clear() should empty the new table. addrman.Clear(); @@ -120,7 +124,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple) vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE)); vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE)); BOOST_CHECK(addrman.Add(vAddr, source)); - BOOST_CHECK_EQUAL(addrman.size(), 2); + BOOST_CHECK(addrman.size() >= 1); } BOOST_AUTO_TEST_CASE(addrman_ports) From ea3afb995fc120d85c011590a704a5bb9cfa464e Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 22 May 2017 08:59:11 +0200 Subject: [PATCH 271/987] Merge #10433: [tests] improve tmpdir structure b040243 [tests] improve tmpdir structure (John Newbery) Tree-SHA512: b21ad555c3c23a43087b893ad18bd2398e1df91b82c0bf1804d07fdb582600a1c339e6f4aaca58074e52f146f459943a0e492abc045b2666d4a3a7e0e455d6dd --- .../test_framework/test_framework.py | 13 ++++----- test/functional/test_runner.py | 29 ++++++++++++++----- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 8ab9afb99644..709069553bc7 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -121,8 +121,7 @@ def main(self): help="Source directory containing dashd/dash-cli (default: %default)") parser.add_option("--cachedir", dest="cachedir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__))+"/../../cache"), help="Directory for caching pregenerated datadirs") - parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), - help="Root directory for datadirs") + parser.add_option("--tmpdir", dest="tmpdir", help="Root directory for datadirs") parser.add_option("-l", "--loglevel", dest="loglevel", default="INFO", help="log events at this level and higher to the console. Can be set to DEBUG, INFO, WARNING, ERROR or CRITICAL. Passing --loglevel DEBUG will output all logs to console. Note that logs at all levels are always written to the test_framework.log file in the temporary test directory.") parser.add_option("--tracerpc", dest="trace_rpc", default=False, action="store_true", @@ -136,9 +135,6 @@ def main(self): self.add_options(parser) (self.options, self.args) = parser.parse_args() - # backup dir variable for removal at cleanup - self.options.root, self.options.tmpdir = self.options.tmpdir, self.options.tmpdir + '/' + str(self.options.port_seed) - if self.options.coveragedir: enable_coverage(self.options.coveragedir) @@ -149,7 +145,10 @@ def main(self): check_json_precision() # Set up temp directory and start logging - os.makedirs(self.options.tmpdir, exist_ok=False) + if self.options.tmpdir: + os.makedirs(self.options.tmpdir, exist_ok=False) + else: + self.options.tmpdir = tempfile.mkdtemp(prefix="test") self._start_logging() success = False @@ -183,8 +182,6 @@ def main(self): if not self.options.nocleanup and not self.options.noshutdown and success: self.log.info("Cleaning up") shutil.rmtree(self.options.tmpdir) - if not os.listdir(self.options.root): - os.rmdir(self.options.root) else: self.log.warning("Not cleaning up dir %s" % self.options.tmpdir) if os.getenv("PYTHON_DEBUG", ""): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index c58d3fe7fee7..c1fe6d477cd6 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -16,6 +16,7 @@ import argparse import configparser +import datetime import os import time import shutil @@ -184,6 +185,7 @@ def main(): parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.') parser.add_argument('--quiet', '-q', action='store_true', help='only print results summary and failure logs') parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.') + parser.add_argument('--tmpdirprefix', '-t', default=tempfile.gettempdir(), help="Root directory for datadirs") args, unknown_args = parser.parse_known_args() # args to be passed on always start with two dashes; tests are the remaining unknown args @@ -201,6 +203,12 @@ def main(): logging_level = logging.INFO if args.quiet else logging.DEBUG logging.basicConfig(format='%(message)s', level=logging_level) + # Create base test directory + tmpdir = "%s/bitcoin_test_runner_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S")) + os.makedirs(tmpdir) + + logging.debug("Temporary test directory at %s" % tmpdir) + enable_wallet = config["components"].getboolean("ENABLE_WALLET") enable_utils = config["components"].getboolean("ENABLE_UTILS") enable_bitcoind = config["components"].getboolean("ENABLE_BITCOIND") @@ -261,9 +269,9 @@ def main(): if not args.keepcache: shutil.rmtree("%s/test/cache" % config["environment"]["BUILDDIR"], ignore_errors=True) - run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args) + run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], tmpdir, args.jobs, args.coverage, passon_args) -def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=False, args=[]): +def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_coverage=False, args=[]): # Warn if dashd is already running (unix only) try: pidof_output = subprocess.check_output(["pidof", "dashd"]) @@ -296,10 +304,10 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal if len(test_list) > 1 and jobs > 1: # Populate cache - subprocess.check_output([tests_dir + 'create_cache.py'] + flags) + subprocess.check_output([tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir]) #Run Tests - job_queue = TestHandler(jobs, tests_dir, test_list, flags) + job_queue = TestHandler(jobs, tests_dir, tmpdir, test_list, flags) time0 = time.time() test_results = [] @@ -326,6 +334,10 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal logging.debug("Cleaning up coverage data") coverage.cleanup() + # Clear up the temp directory if all subdirectories are gone + if not os.listdir(tmpdir): + os.rmdir(tmpdir) + all_passed = all(map(lambda test_result: test_result.was_successful, test_results)) sys.exit(not all_passed) @@ -353,10 +365,11 @@ class TestHandler: Trigger the testscrips passed in via the list. """ - def __init__(self, num_tests_parallel, tests_dir, test_list=None, flags=None): + def __init__(self, num_tests_parallel, tests_dir, tmpdir, test_list=None, flags=None): assert(num_tests_parallel >= 1) self.num_jobs = num_tests_parallel self.tests_dir = tests_dir + self.tmpdir = tmpdir self.test_list = test_list self.flags = flags self.num_running = 0 @@ -371,13 +384,15 @@ def get_next(self): # Add tests self.num_running += 1 t = self.test_list.pop(0) - port_seed = ["--portseed={}".format(len(self.test_list) + self.portseed_offset)] + portseed = len(self.test_list) + self.portseed_offset + portseed_arg = ["--portseed={}".format(portseed)] log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) test_argv = t.split() + tmpdir = ["--tmpdir=%s/%s_%s" % (self.tmpdir, re.sub(".py$", "", test_argv[0]), portseed)] self.jobs.append((t, time.time(), - subprocess.Popen([self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + port_seed, + subprocess.Popen([self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir, universal_newlines=True, stdout=log_stdout, stderr=log_stderr), From 9a40d488d4695d9ff6fd36f31c1c2cbdae64508a Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 10 Jun 2019 17:10:09 -0500 Subject: [PATCH 272/987] change include Signed-off-by: Pasta --- src/test/torcontrol_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/torcontrol_tests.cpp b/src/test/torcontrol_tests.cpp index b7affaacde58..6d48dca1ab97 100644 --- a/src/test/torcontrol_tests.cpp +++ b/src/test/torcontrol_tests.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. // -#include "test/test_bitcoin.h" +#include "test/test_dash.h" #include "torcontrol.cpp" #include From ae864eb2ce7437f3c2e403afedc0654ba196010a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 22 May 2017 19:53:40 +0200 Subject: [PATCH 273/987] Merge #10390: [wallet] remove minimum total fee option 091a9ae remove minimum total fee option (Gregory Sanders) Tree-SHA512: 9be4df3dab0219f30917211408f47b242f7c96dd7663b06ab1cf3cc63027f14956dc680883be6c58673b6452d0f339cf893694e4f21d0d248e70760614d5a344 --- src/qt/coincontroldialog.cpp | 4 +--- src/qt/forms/sendcoinsdialog.ui | 13 ------------- src/qt/sendcoinsdialog.cpp | 24 ------------------------ src/wallet/coincontrol.h | 3 --- src/wallet/wallet.cpp | 5 ++--- 5 files changed, 3 insertions(+), 46 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index b9d3a9bd78c6..87895c644323 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -558,8 +558,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // Fee nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, ::mempool, ::feeEstimator); - if (nPayFee > 0 && coinControl->nMinimumTotalFee > nPayFee) - nPayFee = coinControl->nMinimumTotalFee; // InstantSend Fee if (coinControl->fUseInstantSend) nPayFee = std::max(nPayFee, CTxLockRequest(txDummy).GetMinFee(true)); @@ -627,7 +625,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) l5->setText(((nBytes > 0) ? ASYMP_UTF8 : "") + QString::number(nBytes)); // Bytes l7->setText(fDust ? tr("yes") : tr("no")); // Dust l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change - if (nPayFee > 0 && (coinControl->nMinimumTotalFee < nPayFee)) + if (nPayFee > 0) { l3->setText(ASYMP_UTF8 + l3->text()); l4->setText(ASYMP_UTF8 + l4->text()); diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 4a210ceacde5..45953e7a22f0 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -861,19 +861,6 @@
- - - - If the custom fee is set to 1000 duffs and the transaction is only 250 bytes, then "per kilobyte" only pays 250 duffs in fee,<br />while "total at least" pays 1000 duffs. For transactions bigger than a kilobyte both pay by kilobyte. - - - total at least - - - groupCustomFee - - - diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 0649e6d8fa85..b50f73aeab80 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -151,7 +151,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p ui->groupFee->setId(ui->radioCustomFee, 1); ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true); ui->groupCustomFee->setId(ui->radioCustomPerKilobyte, 0); - ui->groupCustomFee->setId(ui->radioCustomAtLeast, 1); ui->groupCustomFee->button((int)std::max(0, std::min(1, settings.value("nCustomFeeRadio").toInt())))->setChecked(true); ui->customFee->setValue(settings.value("nTransactionFee").toLongLong()); ui->checkBoxMinimumFee->setChecked(settings.value("fPayOnlyMinFee").toBool()); @@ -717,7 +716,6 @@ void SendCoinsDialog::updateFeeSectionControls() ui->checkBoxMinimumFee ->setEnabled(ui->radioCustomFee->isChecked()); ui->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked()); ui->radioCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); - ui->radioCustomAtLeast ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked() && CoinControlDialog::coinControl->HasSelected()); ui->customFee ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); } @@ -728,19 +726,12 @@ void SendCoinsDialog::updateGlobalFeeVariables() int nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; payTxFee = CFeeRate(0); - // set nMinimumTotalFee to 0 to not accidentally pay a custom fee - CoinControlDialog::coinControl->nMinimumTotalFee = 0; - // show the estimated required time for confirmation ui->confirmationTargetLabel->setText(GUIUtil::formatDurationStr(nConfirmTarget * Params().GetConsensus().nPowTargetSpacing) + " / " + tr("%n block(s)", "", nConfirmTarget)); } else { payTxFee = CFeeRate(ui->customFee->value()); - - // if user has selected to set a minimum absolute fee, pass the value to coincontrol - // set nMinimumTotalFee to 0 in case of user has selected that the fee is per KB - CoinControlDialog::coinControl->nMinimumTotalFee = ui->radioCustomAtLeast->isChecked() ? ui->customFee->value() : 0; } } @@ -939,21 +930,6 @@ void SendCoinsDialog::coinControlUpdateLabels() if (!model || !model->getOptionsModel()) return; - if (model->getOptionsModel()->getCoinControlFeatures()) - { - // enable minimum absolute fee UI controls - ui->radioCustomAtLeast->setVisible(true); - - // only enable the feature if inputs are selected - ui->radioCustomAtLeast->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked() &&CoinControlDialog::coinControl->HasSelected()); - } - else - { - // in case coin control is disabled (=default), hide minimum absolute fee UI controls - ui->radioCustomAtLeast->setVisible(false); - return; - } - // set pay amounts CoinControlDialog::payAmounts.clear(); CoinControlDialog::fSubtractFeeFromAmount = false; diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index 2d06635f6121..1946b601b188 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -20,8 +20,6 @@ class CCoinControl bool fRequireAllInputs; //! Includes watch only addresses which match the ISMINE_WATCH_SOLVABLE criteria bool fAllowWatchOnly; - //! Minimum absolute fee (not per kilobyte) - CAmount nMinimumTotalFee; //! Override estimated feerate bool fOverrideFeeRate; //! Feerate to use if overrideFeeRate is true @@ -43,7 +41,6 @@ class CCoinControl setSelected.clear(); fUseInstantSend = false; fUsePrivateSend = true; - nMinimumTotalFee = 0; nFeeRate = CFeeRate(0); fOverrideFeeRate = false; nConfirmTarget = 0; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6856c45dc7fa..8018a208e7a7 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3683,9 +3683,8 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT currentConfirmationTarget = coinControl->nConfirmTarget; CAmount nFeeNeeded = std::max(nFeePay, GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator)); - if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) { - nFeeNeeded = coinControl->nMinimumTotalFee; - } + if (coinControl && coinControl->fOverrideFeeRate) + nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes); if(fUseInstantSend) { nFeeNeeded = std::max(nFeeNeeded, CTxLockRequest(txNew).GetMinFee(true)); } From 3dae8f270c02987a37fdf43deaba87b393808d1c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 23 May 2017 17:53:00 +0200 Subject: [PATCH 274/987] Merge #10372: Add perf counter data to GetStrongRandBytes state in scheduler 888cce5 Add perf counter data to GetStrongRandBytes state in scheduler (Matt Corallo) 399fb8f Add internal method to add new random data to our internal RNG state (Matt Corallo) Tree-SHA512: 9732a3804d015eaf48d56b60c73880014845fd17a098f1ac2eff6bd50a4beb8b8be65956ac1f0d641e96e3a53c17daddd919401edbf2e3797c3fb687730fb913 --- src/random.cpp | 33 +++++++++++++++++++++++++++++++++ src/random.h | 7 +++++++ src/scheduler.cpp | 6 ++++++ 3 files changed, 46 insertions(+) diff --git a/src/random.cpp b/src/random.cpp index 3c47feb1a212..4f28ebf4948c 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -203,10 +203,43 @@ void GetRandBytes(unsigned char* buf, int num) } } +static void AddDataToRng(void* data, size_t len); + +void RandAddSeedSleep() +{ + int64_t nPerfCounter1 = GetPerformanceCounter(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + int64_t nPerfCounter2 = GetPerformanceCounter(); + + // Combine with and update state + AddDataToRng(&nPerfCounter1, sizeof(nPerfCounter1)); + AddDataToRng(&nPerfCounter2, sizeof(nPerfCounter2)); + + memory_cleanse(&nPerfCounter1, sizeof(nPerfCounter1)); + memory_cleanse(&nPerfCounter2, sizeof(nPerfCounter2)); +} + + static std::mutex cs_rng_state; static unsigned char rng_state[32] = {0}; static uint64_t rng_counter = 0; +static void AddDataToRng(void* data, size_t len) { + CSHA512 hasher; + hasher.Write((const unsigned char*)&len, sizeof(len)); + hasher.Write((const unsigned char*)data, len); + unsigned char buf[64]; + { + std::unique_lock lock(cs_rng_state); + hasher.Write(rng_state, sizeof(rng_state)); + hasher.Write((const unsigned char*)&rng_counter, sizeof(rng_counter)); + ++rng_counter; + hasher.Finalize(buf); + memcpy(rng_state, buf + 32, 32); + } + memory_cleanse(buf, 64); +} + void GetStrongRandBytes(unsigned char* out, int num) { assert(num <= 32); diff --git a/src/random.h b/src/random.h index 392d5407f496..29b7b2c8abce 100644 --- a/src/random.h +++ b/src/random.h @@ -25,6 +25,13 @@ uint256 GetRandHash(); bool GetRandBool(double rate); +/** + * Add a little bit of randomness to the output of GetStrongRangBytes. + * This sleeps for a millisecond, so should only be called when there is + * no other work to be done. + */ +void RandAddSeedSleep(); + /** * Function to gather random data from multiple sources, failing whenever any * of those source fail to provide a result. diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 56d9e01ee1b4..da3bd25f35e7 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -4,6 +4,7 @@ #include "scheduler.h" +#include "random.h" #include "reverselock.h" #include @@ -39,6 +40,11 @@ void CScheduler::serviceQueue() // is called. while (!shouldStop()) { try { + if (!shouldStop() && taskQueue.empty()) { + reverse_lock > rlock(lock); + // Use this chance to get a tiny bit more entropy + RandAddSeedSleep(); + } while (!shouldStop() && taskQueue.empty()) { // Wait until there is something to do. newTaskScheduled.wait(lock); From 324c588db868c453e73b6ca76b1f7787923608cb Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 23 May 2017 19:07:29 +0200 Subject: [PATCH 275/987] Merge #9571: RPC: getblockchaininfo returns BIP signaling statistics 557c9a6 RPC: getblockchaininfo: BIP9 stats (Matthew Zipkin) Tree-SHA512: ecf0bf47f04f92becc77acc649fdfa270e768939acce42df39d30069398d40d9a30539862f7c307e08239f78d5c58c470ca5f6e717d2ab8e24db9be0dd7bec0c --- src/rpc/blockchain.cpp | 22 +++++++++++-- src/validation.cpp | 6 ++++ src/validation.h | 3 ++ src/versionbits.cpp | 36 +++++++++++++++++++++- src/versionbits.h | 10 ++++++ test/functional/bip9-softforks.py | 51 ++++++++++++++++++++++++++++--- 6 files changed, 121 insertions(+), 7 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 90f8e005d098..96463f5e9f9a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -209,7 +209,7 @@ void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex) latestblock.hash = pindex->GetBlockHash(); latestblock.height = pindex->nHeight; } - cond_blockchange.notify_all(); + cond_blockchange.notify_all(); } UniValue waitfornewblock(const JSONRPCRequest& request) @@ -1338,6 +1338,17 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime)); rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout)); rv.push_back(Pair("since", VersionBitsTipStateSinceHeight(consensusParams, id))); + if (THRESHOLD_STARTED == thresholdState) + { + UniValue statsUV(UniValue::VOBJ); + BIP9Stats statsStruct = VersionBitsTipStatistics(consensusParams, id); + statsUV.push_back(Pair("period", statsStruct.period)); + statsUV.push_back(Pair("threshold", statsStruct.threshold)); + statsUV.push_back(Pair("elapsed", statsStruct.elapsed)); + statsUV.push_back(Pair("count", statsStruct.count)); + statsUV.push_back(Pair("possible", statsStruct.possible)); + rv.push_back(Pair("statistics", statsUV)); + } return rv; } @@ -1388,7 +1399,14 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) " \"windowProgress\": xx, (numeric) the progress (between 0 and 1) for activation of this softfork (only for \"started\" status)\n" " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" - " \"since\": xx (numeric) height of the first block to which the status applies\n" + " \"since\": xx, (numeric) height of the first block to which the status applies\n" + " \"statistics\": { (object) numeric statistics about BIP9 signalling for a softfork (only for \"started\" status)\n" + " \"period\": xx, (numeric) the length in blocks of the BIP9 signalling period \n" + " \"threshold\": xx, (numeric) the number of blocks with the version bit set required to activate the feature \n" + " \"elapsed\": xx, (numeric) the number of blocks elapsed since the beginning of the current period \n" + " \"count\": xx, (numeric) the number of blocks with the version bit set in the current period \n" + " \"possible\": xx (boolean) returns false if there are not enough blocks left in this period to pass activation threshold \n" + " }\n" " }\n" " }\n" "}\n" diff --git a/src/validation.cpp b/src/validation.cpp index 9a6502d9794e..cdcfd943e149 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4547,6 +4547,12 @@ ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::D return VersionBitsState(chainActive.Tip(), params, pos, versionbitscache); } +BIP9Stats VersionBitsTipStatistics(const Consensus::Params& params, Consensus::DeploymentPos pos) +{ + LOCK(cs_main); + return VersionBitsStatistics(chainActive.Tip(), params, pos); +} + int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos) { LOCK(cs_main); diff --git a/src/validation.h b/src/validation.h index 5a9285bff477..e034aff0feea 100644 --- a/src/validation.h +++ b/src/validation.h @@ -327,6 +327,9 @@ std::string FormatStateMessage(const CValidationState &state); /** Get the BIP9 state for a given deployment at the current tip. */ ThresholdState VersionBitsTipState(const Consensus::Params& params, Consensus::DeploymentPos pos); +/** Get the numerical statistics for the BIP9 state for a given deployment at the current tip. */ +BIP9Stats VersionBitsTipStatistics(const Consensus::Params& params, Consensus::DeploymentPos pos); + /** Get the block height at which the BIP9 deployment switched into the state for the block building on the current tip. */ int VersionBitsTipStateSinceHeight(const Consensus::Params& params, Consensus::DeploymentPos pos); diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 4cff61500936..1cd282a7ca67 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -3,7 +3,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "versionbits.h" - #include "consensus/params.h" const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = { @@ -123,6 +122,36 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* return state; } +// return the numerical statistics of blocks signalling the specified BIP9 condition in this current period +BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params) const +{ + BIP9Stats stats; + + stats.period = Period(params); + stats.threshold = Threshold(params); + + if (pindex == NULL) + return stats; + + // Find beginning of period + const CBlockIndex* pindexEndOfPrevPeriod = pindex->GetAncestor(pindex->nHeight - ((pindex->nHeight + 1) % stats.period)); + stats.elapsed = pindex->nHeight - pindexEndOfPrevPeriod->nHeight; + + // Count from current block to beginning of period + int count = 0; + const CBlockIndex* currentIndex = pindex; + while (pindexEndOfPrevPeriod->nHeight != currentIndex->nHeight){ + if (Condition(currentIndex, params)) + count++; + currentIndex = currentIndex->pprev; + } + + stats.count = count; + stats.possible = (stats.period - stats.threshold ) >= (stats.elapsed - count); + + return stats; +} + int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const { const ThresholdState initialState = GetStateFor(pindexPrev, params, cache); @@ -200,6 +229,11 @@ ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus:: return VersionBitsConditionChecker(pos).GetStateFor(pindexPrev, params, cache.caches[pos]); } +BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) +{ + return VersionBitsConditionChecker(pos).GetStateStatisticsFor(pindexPrev, params); +} + int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache) { return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]); diff --git a/src/versionbits.h b/src/versionbits.h index 1615a44986e9..1ff944a89bd9 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -39,6 +39,14 @@ struct BIP9DeploymentInfo { bool check_mn_protocol; }; +struct BIP9Stats { + int period; + int threshold; + int elapsed; + int count; + bool possible; +}; + extern const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[]; /** @@ -53,6 +61,7 @@ class AbstractThresholdConditionChecker { virtual int Threshold(const Consensus::Params& params) const =0; public: + BIP9Stats GetStateStatisticsFor(const CBlockIndex* pindex, const Consensus::Params& params) const; // Note that the functions below take a pindexPrev as input: they compute information for block B based on its parent. ThresholdState GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const; int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const; @@ -67,6 +76,7 @@ struct VersionBitsCache }; ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); +BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos); int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); int VersionBitsCountBlocksInWindow(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos); uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos); diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index da7d1efa5dcc..7040e6109b49 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -99,12 +99,43 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu assert_equal(self.get_bip9_status(bipName)['status'], 'started') assert_equal(self.get_bip9_status(bipName)['since'], 144) + assert_equal(self.get_bip9_status(bipName)['statistics']['elapsed'], 0) + assert_equal(self.get_bip9_status(bipName)['statistics']['count'], 0) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) assert_equal(tmpl['vbavailable'][bipName], bitno) assert_equal(tmpl['vbrequired'], 0) assert(tmpl['version'] & activated_version) + # Test 1-A + # check stats after max number of "signalling not" blocks such that LOCKED_IN still possible this period + test_blocks = self.generate_blocks(36, 4, test_blocks) # 0x00000004 (signalling not) + test_blocks = self.generate_blocks(10, activated_version) # 0x20000001 (signalling ready) + yield TestInstance(test_blocks, sync_every_block=False) + + assert_equal(self.get_bip9_status(bipName)['statistics']['elapsed'], 46) + assert_equal(self.get_bip9_status(bipName)['statistics']['count'], 10) + assert_equal(self.get_bip9_status(bipName)['statistics']['possible'], True) + + # Test 1-B + # check stats after one additional "signalling not" block -- LOCKED_IN no longer possible this period + test_blocks = self.generate_blocks(1, 4, test_blocks) # 0x00000004 (signalling not) + yield TestInstance(test_blocks, sync_every_block=False) + + assert_equal(self.get_bip9_status(bipName)['statistics']['elapsed'], 47) + assert_equal(self.get_bip9_status(bipName)['statistics']['count'], 10) + assert_equal(self.get_bip9_status(bipName)['statistics']['possible'], False) + + # Test 1-C + # finish period with "ready" blocks, but soft fork will still fail to advance to LOCKED_IN + test_blocks = self.generate_blocks(97, activated_version) # 0x20000001 (signalling ready) + yield TestInstance(test_blocks, sync_every_block=False) + + assert_equal(self.get_bip9_status(bipName)['statistics']['elapsed'], 0) + assert_equal(self.get_bip9_status(bipName)['statistics']['count'], 0) + assert_equal(self.get_bip9_status(bipName)['statistics']['possible'], True) + assert_equal(self.get_bip9_status(bipName)['status'], 'started') + # Test 2 # Fail to achieve LOCKED_IN 100 out of 144 signal bit 1 # using a variety of bits to simulate multiple parallel softforks @@ -116,6 +147,8 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu assert_equal(self.get_bip9_status(bipName)['status'], 'started') assert_equal(self.get_bip9_status(bipName)['since'], 144) + assert_equal(self.get_bip9_status(bipName)['statistics']['elapsed'], 0) + assert_equal(self.get_bip9_status(bipName)['statistics']['count'], 0) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) assert_equal(tmpl['vbavailable'][bipName], bitno) @@ -125,14 +158,24 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu # Test 3 # 108 out of 144 signal bit 1 to achieve LOCKED_IN # using a variety of bits to simulate multiple parallel softforks - test_blocks = self.generate_blocks(58, activated_version) # 0x20000001 (signalling ready) + test_blocks = self.generate_blocks(57, activated_version) # 0x20000001 (signalling ready) test_blocks = self.generate_blocks(26, 4, test_blocks) # 0x00000004 (signalling not) test_blocks = self.generate_blocks(50, activated_version, test_blocks) # 0x20000101 (signalling ready) test_blocks = self.generate_blocks(10, 4, test_blocks) # 0x20010000 (signalling not) yield TestInstance(test_blocks, sync_every_block=False) + # check counting stats and "possible" flag before last block of this period achieves LOCKED_IN... + assert_equal(self.get_bip9_status(bipName)['statistics']['elapsed'], 143) + assert_equal(self.get_bip9_status(bipName)['statistics']['count'], 107) + assert_equal(self.get_bip9_status(bipName)['statistics']['possible'], True) + assert_equal(self.get_bip9_status(bipName)['status'], 'started') + + # ...continue with Test 3 + test_blocks = self.generate_blocks(1, activated_version) # 0x20000001 (signalling ready) + yield TestInstance(test_blocks, sync_every_block=False) + assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in') - assert_equal(self.get_bip9_status(bipName)['since'], 432) + assert_equal(self.get_bip9_status(bipName)['since'], 576) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) @@ -142,7 +185,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance(test_blocks, sync_every_block=False) assert_equal(self.get_bip9_status(bipName)['status'], 'locked_in') - assert_equal(self.get_bip9_status(bipName)['since'], 432) + assert_equal(self.get_bip9_status(bipName)['since'], 576) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName not in tmpl['rules']) @@ -168,7 +211,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu yield TestInstance([[block, True]]) assert_equal(self.get_bip9_status(bipName)['status'], 'active') - assert_equal(self.get_bip9_status(bipName)['since'], 576) + assert_equal(self.get_bip9_status(bipName)['since'], 720) tmpl = self.nodes[0].getblocktemplate({}) assert(bipName in tmpl['rules']) assert(bipName not in tmpl['vbavailable']) From 0477eb4b3906f6df600d8f1a44984322b88745de Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 23 May 2017 19:37:52 +0200 Subject: [PATCH 276/987] Merge #9539: [net] Avoid initialization to a value that is never read 5844609 [net] Avoid initialization to a value that is never read (practicalswift) Tree-SHA512: 068c3fba58034187f546688bc9b8b7317e0657e797850613fb6289a4efc28637e4d06a0fa5e57480538c6b8340ed6d6a6c6f9a96f130b698d5d60975490a03d8 --- src/netbase.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/netbase.cpp b/src/netbase.cpp index f16cb8f343e3..175e2b8100ca 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -668,13 +668,14 @@ std::string NetworkErrorString(int err) std::string NetworkErrorString(int err) { char buf[256]; - const char *s = buf; buf[0] = 0; /* Too bad there are two incompatible implementations of the * thread-safe strerror. */ + const char *s; #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */ s = strerror_r(err, buf, sizeof(buf)); #else /* POSIX variant always returns message in buffer */ + s = buf; if (strerror_r(err, buf, sizeof(buf))) buf[0] = 0; #endif From 1522230ec1da97a5571ced7bff6a46502a5914e3 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 23 May 2017 14:24:47 -0700 Subject: [PATCH 277/987] Merge #10313: [Consensus] Add constant for maximum stack size cb184b3 Add constant for maximum stack size (Gregory Sanders) Tree-SHA512: 0ec4a28552a6eee7fba8c69278f63c61f095e4ba06cb34456bd0162cd702370d10cca621ae1797a0d5e62fb39814cbb8245d3a7adc007ca39dab7a49cbc925dc --- src/script/interpreter.cpp | 2 +- src/script/script.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 6d309e0fd52c..8b06192aaedd 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1002,7 +1002,7 @@ bool EvalScript(std::vector >& stack, const CScript& } // Size limits - if (stack.size() + altstack.size() > 1000) + if (stack.size() + altstack.size() > MAX_STACK_SIZE) return set_error(serror, SCRIPT_ERR_STACK_SIZE); } } diff --git a/src/script/script.h b/src/script/script.h index 74cbb2bf136f..6a9f67d37fd3 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -30,6 +30,9 @@ static const int MAX_PUBKEYS_PER_MULTISIG = 20; // Maximum script length in bytes static const int MAX_SCRIPT_SIZE = 10000; +// Maximum number of values on script interpreter stack +static const int MAX_STACK_SIZE = 1000; + // Threshold for nLockTime: below this value it is interpreted as block number, // otherwise as UNIX timestamp. static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC From 9ba69fd5cc5748a3fa7e5afd221db5ce1825fd0c Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 19 Jun 2019 00:24:14 -0500 Subject: [PATCH 278/987] add serialize.h import Signed-off-by: Pasta --- src/spentindex.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/spentindex.h b/src/spentindex.h index dec3a00070d3..f4628bb6c690 100644 --- a/src/spentindex.h +++ b/src/spentindex.h @@ -9,6 +9,7 @@ #include "uint256.h" #include "amount.h" #include "script/script.h" +#include "serialize.h" struct CSpentIndexKey { uint256 txid; From de9629553c9fa240e22d825230d08ca6cd94ad6c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 26 Apr 2017 12:48:45 +0200 Subject: [PATCH 279/987] Merge #9614: [wallet] [refactor] Simplify getbalance implementation 02d9f50 [wallet] Remove unneeded legacy getbalance code (Russell Yanofsky) 82b7dc3 [wallet] Add GetLegacyBalance method to simplify getbalance RPC (Russell Yanofsky) Tree-SHA512: c3b890ff1f5a3df7e886309bad94bdf5cc3c12b72983bb79c72f8655ce16edf581bff0faaade2f18c2cb723f50d516e53f87792f81c3f8143b0c4377c0d80e87 --- src/wallet/rpcwallet.cpp | 39 ++---------- src/wallet/wallet.cpp | 124 ++++++++++++++++++--------------------- src/wallet/wallet.h | 8 +-- 3 files changed, 66 insertions(+), 105 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0ebcb0f246f8..3f6fb3bca157 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -840,6 +840,8 @@ UniValue getbalance(const JSONRPCRequest& request) if (request.params.size() == 0) return ValueFromAmount(pwallet->GetBalance()); + const std::string* account = request.params[0].get_str() != "*" ? &request.params[0].get_str() : nullptr; + int nMinDepth = 1; if (request.params.size() > 1) nMinDepth = request.params[1].get_int(); @@ -849,38 +851,7 @@ UniValue getbalance(const JSONRPCRequest& request) if(request.params[3].get_bool()) filter = filter | ISMINE_WATCH_ONLY; - if (request.params[0].get_str() == "*") { - // Calculate total balance a different way from GetBalance() - // (GetBalance() sums up all unspent TxOuts) - // getbalance and "getbalance * 1 true" should return the same number - CAmount nBalance = 0; - for (const std::pair& pairWtx : pwallet->mapWallet) { - const CWalletTx& wtx = pairWtx.second; - if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) - continue; - - CAmount allFee; - std::string strSentAccount; - std::list listReceived; - std::list listSent; - wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); - if ((wtx.GetDepthInMainChain() >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend())) - { - BOOST_FOREACH(const COutputEntry& r, listReceived) - nBalance += r.amount; - } - BOOST_FOREACH(const COutputEntry& s, listSent) - nBalance -= s.amount; - nBalance -= allFee; - } - return ValueFromAmount(nBalance); - } - - std::string strAccount = AccountFromValue(request.params[0]); - - CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, filter, fAddLocked); - - return ValueFromAmount(nBalance); + return ValueFromAmount(pwallet->GetLegacyBalance(filter, nMinDepth, account, fAddLocked)); } UniValue getunconfirmedbalance(const JSONRPCRequest &request) @@ -1012,7 +983,7 @@ UniValue sendfrom(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); // Check funds - CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLocked); + CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount, fAddLocked); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -1123,7 +1094,7 @@ UniValue sendmany(const JSONRPCRequest& request) EnsureWalletIsUnlocked(pwallet); // Check funds - CAmount nBalance = pwallet->GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE, fAddLocked); + CAmount nBalance = pwallet->GetLegacyBalance(ISMINE_SPENDABLE, nMinDepth, &strAccount, fAddLocked); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 8018a208e7a7..fa8b081f142a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1819,41 +1819,6 @@ void CWalletTx::GetAmounts(std::list& listReceived, } -void CWalletTx::GetAccountAmounts(const std::string& strAccount, CAmount& nReceived, - CAmount& nSent, CAmount& nFee, const isminefilter& filter) const -{ - nReceived = nSent = nFee = 0; - - CAmount allFee; - std::string strSentAccount; - std::list listReceived; - std::list listSent; - GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); - - if (strAccount == strSentAccount) - { - BOOST_FOREACH(const COutputEntry& s, listSent) - nSent += s.amount; - nFee = allFee; - } - { - LOCK(pwallet->cs_wallet); - BOOST_FOREACH(const COutputEntry& r, listReceived) - { - if (pwallet->mapAddressBook.count(r.destination)) - { - std::map::const_iterator mi = pwallet->mapAddressBook.find(r.destination); - if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount) - nReceived += r.amount; - } - else if (strAccount.empty()) - { - nReceived += r.amount; - } - } - } -} - /** * Scan the block chain (starting in pindexStart) for transactions * from or to us. If fUpdate is true, found transactions that already @@ -2536,6 +2501,49 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const return nTotal; } +// Calculate total balance in a different way from GetBalance. The biggest +// difference is that GetBalance sums up all unspent TxOuts paying to the +// wallet, while this sums up both spent and unspent TxOuts paying to the +// wallet, and then subtracts the values of TxIns spending from the wallet. This +// also has fewer restrictions on which unconfirmed transactions are considered +// trusted. +CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account, const bool fAddLocked) const +{ + LOCK2(cs_main, cs_wallet); + + CAmount balance = 0; + for (const auto& entry : mapWallet) { + const CWalletTx& wtx = entry.second; + const int depth = wtx.GetDepthInMainChain(); + if (depth < 0 || !CheckFinalTx(*wtx.tx) || wtx.GetBlocksToMaturity() > 0) { + continue; + } + + // Loop through tx outputs and add incoming payments. For outgoing txs, + // treat change outputs specially, as part of the amount debited. + CAmount debit = wtx.GetDebit(filter); + const bool outgoing = debit > 0; + for (const CTxOut& out : wtx.tx->vout) { + if (outgoing && IsChange(out)) { + debit -= out.nValue; + } else if (IsMine(out) & filter && (depth >= minDepth || (fAddLocked && wtx.IsLockedByInstantSend())) && (!account || *account == GetAccountName(out.scriptPubKey))) { + balance += out.nValue; + } + } + + // For outgoing txs, subtract amount debited. + if (outgoing && (!account || *account == wtx.strFromAccount)) { + balance -= debit; + } + } + + if (account) { + balance += CWalletDB(*dbw).GetAccountCreditDebit(*account); + } + + return balance; +} + void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlySafe, const CCoinControl *coinControl, bool fIncludeZeroValue, AvailableCoinsType nCoinType, bool fUseInstantSend) const { vCoins.clear(); @@ -4022,6 +4030,21 @@ bool CWallet::DelAddressBook(const CTxDestination& address) return CWalletDB(*dbw).EraseName(CBitcoinAddress(address).ToString()); } +const std::string& CWallet::GetAccountName(const CScript& scriptPubKey) const +{ + CTxDestination address; + if (ExtractDestination(scriptPubKey, address) && !scriptPubKey.IsUnspendable()) { + auto mi = mapAddressBook.find(address); + if (mi != mapAddressBook.end()) { + return mi->second.name; + } + } + // A scriptPubKey that doesn't have an entry in the address book is + // associated with the default account (""). + const static std::string DEFAULT_ACCOUNT_NAME; + return DEFAULT_ACCOUNT_NAME; +} + bool CWallet::SetDefaultKey(const CPubKey &vchPubKey) { if (!CWalletDB(*dbw).WriteDefaultKey(vchPubKey)) @@ -4377,37 +4400,6 @@ std::set< std::set > CWallet::GetAddressGroupings() return ret; } -CAmount CWallet::GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked) -{ - CWalletDB walletdb(*dbw); - return GetAccountBalance(walletdb, strAccount, nMinDepth, filter, fAddLocked); -} - -CAmount CWallet::GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked) -{ - CAmount nBalance = 0; - - // Tally wallet transactions - for (std::map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) - { - const CWalletTx& wtx = (*it).second; - if (!CheckFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0) - continue; - - CAmount nReceived, nSent, nFee; - wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); - - if (nReceived != 0 && ((wtx.GetDepthInMainChain() >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend()))) - nBalance += nReceived; - nBalance -= nSent + nFee; - } - - // Tally internal accounting entries - nBalance += walletdb.GetAccountCreditDebit(strAccount); - - return nBalance; -} - std::set CWallet::GetAccountAddresses(const std::string& strAccount) const { LOCK(cs_wallet); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 95120d27af24..b8e0b49f1558 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -495,9 +495,6 @@ class CWalletTx : public CMerkleTx void GetAmounts(std::list& listReceived, std::list& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const; - void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived, - CAmount& nSent, CAmount& nFee, const isminefilter& filter) const; - bool IsFromMe(const isminefilter& filter) const { return (GetDebit(filter) > 0); @@ -1020,6 +1017,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface CAmount GetWatchOnlyBalance() const; CAmount GetUnconfirmedWatchOnlyBalance() const; CAmount GetImmatureWatchOnlyBalance() const; + CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account, const bool fAddLocked) const; CAmount GetAnonymizableBalance(bool fSkipDenominated = false, bool fSkipUnconfirmed = true) const; CAmount GetAnonymizedBalance() const; @@ -1078,8 +1076,6 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface std::set< std::set > GetAddressGroupings(); std::map GetAddressBalances(); - CAmount GetAccountBalance(const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked); - CAmount GetAccountBalance(CWalletDB& walletdb, const std::string& strAccount, int nMinDepth, const isminefilter& filter, bool fAddLocked); std::set GetAccountAddresses(const std::string& strAccount) const; isminetype IsMine(const CTxIn& txin) const; @@ -1111,6 +1107,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface bool DelAddressBook(const CTxDestination& address); + const std::string& GetAccountName(const CScript& scriptPubKey) const; + void Inventory(const uint256 &hash) override { { From 63db304064fb49705a483a91227eb9940ae32f41 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 11 May 2017 19:09:43 +0200 Subject: [PATCH 280/987] Merge #10341: rpc/wallet: Workaround older UniValue which returns a std::string temporary for get_str a637734 rpc/wallet: Workaround older UniValue which returns a std::string temporary for get_str (Luke Dashjr) Tree-SHA512: 8f03f1d301f714f700bf64e259a1c986136fd1ac532f091aa97198a39c131290c320094f4fc38c774c8db4469a75437596b1d933300e4f04037abc158a252bad --- src/wallet/rpcwallet.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3f6fb3bca157..39004fb9c24f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -840,7 +840,8 @@ UniValue getbalance(const JSONRPCRequest& request) if (request.params.size() == 0) return ValueFromAmount(pwallet->GetBalance()); - const std::string* account = request.params[0].get_str() != "*" ? &request.params[0].get_str() : nullptr; + const std::string& account_param = request.params[0].get_str(); + const std::string* account = account_param != "*" ? &account_param : nullptr; int nMinDepth = 1; if (request.params.size() > 1) From 11dbe39b48b244e9e39ab1fda061eb2a62c48f0c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 11 May 2017 19:26:54 +0200 Subject: [PATCH 281/987] Merge #10317: Remove unused Python imports 0c60c63 Remove unused Python imports (practicalswift) Tree-SHA512: c7ae6a8ae2c751b771804960498bf270ab022c80fa9e1b39118d5986d890c8cdfc27a3cc24bf28c080d8088ddc11facd1f2881ba2c209cdd819675fda4689d83 --- contrib/devtools/github-merge.py | 2 +- test/functional/blockchain.py | 2 -- test/functional/rpcnamedargs.py | 1 - test/functional/signmessages.py | 1 - test/functional/wallet-accounts.py | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/contrib/devtools/github-merge.py b/contrib/devtools/github-merge.py index a96bb7a6ba30..e9816f7d1916 100755 --- a/contrib/devtools/github-merge.py +++ b/contrib/devtools/github-merge.py @@ -15,7 +15,7 @@ # In case of a clean merge that is accepted by the user, the local branch with # name $BRANCH is overwritten with the merged result, and optionally pushed. from __future__ import division,print_function,unicode_literals -import os,sys +import os from sys import stdin,stdout,stderr import argparse import hashlib diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index ff6148c0c871..700c2788f1d7 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -24,8 +24,6 @@ assert_raises_jsonrpc, assert_is_hex_string, assert_is_hash_string, - start_nodes, - connect_nodes_bi, ) diff --git a/test/functional/rpcnamedargs.py b/test/functional/rpcnamedargs.py index fd81b02ead17..3b286000a167 100755 --- a/test/functional/rpcnamedargs.py +++ b/test/functional/rpcnamedargs.py @@ -8,7 +8,6 @@ from test_framework.util import ( assert_equal, assert_raises_jsonrpc, - start_nodes, ) diff --git a/test/functional/signmessages.py b/test/functional/signmessages.py index d9b16ff3c17d..0b6c50ee38d9 100755 --- a/test/functional/signmessages.py +++ b/test/functional/signmessages.py @@ -5,7 +5,6 @@ """Test RPC commands for signing and verifying messages.""" from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * class SignMessagesTest(BitcoinTestFramework): diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py index 816d7009faef..2cdaa37de86e 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet-accounts.py @@ -15,7 +15,6 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( - start_nodes, assert_equal, ) From fbae76b21e19db370d54726b16b33ec3a9a54dc6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 17 Mar 2017 09:40:14 +0100 Subject: [PATCH 282/987] Merge #10011: build: Fix typo s/HAVE_DONTWAIT/HAVE_MSG_DONTWAIT 5073100 build: Fix typo s/HAVE_DONTWAIT/HAVE_MSG_DONTWAIT (Wladimir J. van der Laan) Tree-SHA512: 2305fd68afe940611da10bdebd4994a12612f610365e980313d7e75e13935252366efcaae6cb52da5f8d7e022a164399a3185b385151276ea3843fdcc231fdb1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 3e6682ceb30a..33b1244bd4ff 100644 --- a/configure.ac +++ b/configure.ac @@ -608,7 +608,7 @@ dnl Check for MSG_DONTWAIT AC_MSG_CHECKING(for MSG_DONTWAIT) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ int f = MSG_DONTWAIT; ]])], - [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_DONTWAIT, 1,[Define this symbol if you have MSG_DONTWAIT]) ], + [ AC_MSG_RESULT(yes); AC_DEFINE(HAVE_MSG_DONTWAIT, 1,[Define this symbol if you have MSG_DONTWAIT]) ], [ AC_MSG_RESULT(no)] ) From 1782b062ccbe48d9fbaf1108f336a5af9e10bfd7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 30 May 2017 07:16:41 +0200 Subject: [PATCH 283/987] Merge #10460: Broadcast address every day, not 9 hours 010d68e Broadcast address every day, not 9 hours (Pieter Wuille) Tree-SHA512: 73a8b44b4b48784616e722b1e63561e35d669c2ee890dbc44e40191fdfd8fc1ef56710f4769ab6ea1f1a48fec0576f200c0b3812ca58fb143e7524006d1afed4 --- src/validation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.h b/src/validation.h index e034aff0feea..0af8b91c4930 100644 --- a/src/validation.h +++ b/src/validation.h @@ -107,7 +107,7 @@ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60; /** Maximum length of reject messages. */ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; /** Average delay between local address broadcasts in seconds. */ -static const unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 24 * 60; +static const unsigned int AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL = 24 * 60 * 60; /** Average delay between peer address broadcasts in seconds. */ static const unsigned int AVG_ADDRESS_BROADCAST_INTERVAL = 30; /** Average delay between trickled inventory transmissions in seconds. From a8566404be7e3ac3fa7032c8e832b168dde8d592 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 30 May 2017 18:42:22 +0200 Subject: [PATCH 284/987] Merge #9208: Improve DisconnectTip performance c1235e3 Add RecursiveDynamicUsage overload for std::shared_ptr (Russell Yanofsky) 71f1903 Store disconnected block transactions outside mempool during reorg (Suhas Daftuar) 9decd64 [qa] Relax assumptions on mempool behavior during reorg (Suhas Daftuar) Tree-SHA512: c160ad853a5cd060d0307af7606a0c77907497ed7033c9599b95e73d83f68fdfcd4214bd8a83db1c5b7a58022722b9de1ed2e6ea2e02f38a7b6c717f079dd0c6 --- src/core_memusage.h | 5 ++ src/txmempool.cpp | 2 +- src/txmempool.h | 99 ++++++++++++++++++++++++++++- src/validation.cpp | 127 ++++++++++++++++++++++++++++--------- src/validation.h | 2 + test/functional/pruning.py | 15 ++++- 6 files changed, 216 insertions(+), 34 deletions(-) diff --git a/src/core_memusage.h b/src/core_memusage.h index 3c4728dd5c2c..a6781556843c 100644 --- a/src/core_memusage.h +++ b/src/core_memusage.h @@ -59,4 +59,9 @@ static inline size_t RecursiveDynamicUsage(const CBlockLocator& locator) { return memusage::DynamicUsage(locator.vHave); } +template +static inline size_t RecursiveDynamicUsage(const std::shared_ptr& p) { + return p ? memusage::DynamicUsage(p) + RecursiveDynamicUsage(*p) : 0; +} + #endif // BITCOIN_CORE_MEMUSAGE_H diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 8a907c468ceb..e2b7686ac337 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -31,7 +31,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFe spendsCoinbase(_spendsCoinbase), sigOpCount(_sigOps), lockPoints(lp) { nTxSize = ::GetSerializeSize(*_tx, SER_NETWORK, PROTOCOL_VERSION); - nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx); + nUsageSize = RecursiveDynamicUsage(tx); nCountWithDescendants = 1; nSizeWithDescendants = nTxSize; diff --git a/src/txmempool.h b/src/txmempool.h index c099fbef23d2..6605c0e084f5 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -28,6 +28,7 @@ #include "boost/multi_index_container.hpp" #include "boost/multi_index/ordered_index.hpp" #include "boost/multi_index/hashed_index.hpp" +#include #include @@ -192,7 +193,7 @@ struct update_lock_points const LockPoints& lp; }; -// extracts a TxMemPoolEntry's transaction hash +// extracts a transaction hash from CTxMempoolEntry or CTransactionRef struct mempoolentry_txid { typedef uint256 result_type; @@ -200,6 +201,11 @@ struct mempoolentry_txid { return entry.GetTx().GetHash(); } + + result_type operator() (const CTransactionRef& tx) const + { + return tx->GetHash(); + } }; /** \class CompareTxMemPoolEntryByDescendantScore @@ -724,4 +730,95 @@ class CCoinsViewMemPool : public CCoinsViewBacked bool GetCoin(const COutPoint &outpoint, Coin &coin) const override; }; +/** + * DisconnectedBlockTransactions + + * During the reorg, it's desirable to re-add previously confirmed transactions + * to the mempool, so that anything not re-confirmed in the new chain is + * available to be mined. However, it's more efficient to wait until the reorg + * is complete and process all still-unconfirmed transactions at that time, + * since we expect most confirmed transactions to (typically) still be + * confirmed in the new chain, and re-accepting to the memory pool is expensive + * (and therefore better to not do in the middle of reorg-processing). + * Instead, store the disconnected transactions (in order!) as we go, remove any + * that are included in blocks in the new chain, and then process the remaining + * still-unconfirmed transactions at the end. + */ + +// multi_index tag names +struct txid_index {}; +struct insertion_order {}; + +struct DisconnectedBlockTransactions { + typedef boost::multi_index_container< + CTransactionRef, + boost::multi_index::indexed_by< + // sorted by txid + boost::multi_index::hashed_unique< + boost::multi_index::tag, + mempoolentry_txid, + SaltedTxidHasher + >, + // sorted by order in the blockchain + boost::multi_index::sequenced< + boost::multi_index::tag + > + > + > indexed_disconnected_transactions; + + // It's almost certainly a logic bug if we don't clear out queuedTx before + // destruction, as we add to it while disconnecting blocks, and then we + // need to re-process remaining transactions to ensure mempool consistency. + // For now, assert() that we've emptied out this object on destruction. + // This assert() can always be removed if the reorg-processing code were + // to be refactored such that this assumption is no longer true (for + // instance if there was some other way we cleaned up the mempool after a + // reorg, besides draining this object). + ~DisconnectedBlockTransactions() { assert(queuedTx.empty()); } + + indexed_disconnected_transactions queuedTx; + uint64_t cachedInnerUsage = 0; + + // Estimate the overhead of queuedTx to be 6 pointers + an allocation, as + // no exact formula for boost::multi_index_contained is implemented. + size_t DynamicMemoryUsage() const { + return memusage::MallocUsage(sizeof(CTransactionRef) + 6 * sizeof(void*)) * queuedTx.size() + cachedInnerUsage; + } + + void addTransaction(const CTransactionRef& tx) + { + queuedTx.insert(tx); + cachedInnerUsage += RecursiveDynamicUsage(tx); + } + + // Remove entries based on txid_index, and update memory usage. + void removeForBlock(const std::vector& vtx) + { + // Short-circuit in the common case of a block being added to the tip + if (queuedTx.empty()) { + return; + } + for (auto const &tx : vtx) { + auto it = queuedTx.find(tx->GetHash()); + if (it != queuedTx.end()) { + cachedInnerUsage -= RecursiveDynamicUsage(*it); + queuedTx.erase(it); + } + } + } + + // Remove an entry by insertion_order index, and update memory usage. + void removeEntry(indexed_disconnected_transactions::index::type::iterator entry) + { + cachedInnerUsage -= RecursiveDynamicUsage(*entry); + queuedTx.get().erase(entry); + } + + void clear() + { + cachedInnerUsage = 0; + queuedTx.clear(); + } +}; + #endif // BITCOIN_TXMEMPOOL_H diff --git a/src/validation.cpp b/src/validation.cpp index cdcfd943e149..b981cef3aa38 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -606,9 +606,59 @@ static bool IsCurrentForFeeEstimation() return true; } +/* Make mempool consistent after a reorg, by re-adding or recursively erasing + * disconnected block transactions from the mempool, and also removing any + * other transactions from the mempool that are no longer valid given the new + * tip/height. + * + * Note: we assume that disconnectpool only contains transactions that are NOT + * confirmed in the current chain nor already in the mempool (otherwise, + * in-mempool descendants of such transactions would be removed). + * + * Passing fAddToMempool=false will skip trying to add the transactions back, + * and instead just erase from the mempool as needed. + */ + +void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool) +{ + AssertLockHeld(cs_main); + std::vector vHashUpdate; + // disconnectpool's insertion_order index sorts the entries from + // oldest to newest, but the oldest entry will be the last tx from the + // latest mined block that was disconnected. + // Iterate disconnectpool in reverse, so that we add transactions + // back to the mempool starting with the earliest transaction that had + // been previously seen in a block. + auto it = disconnectpool.queuedTx.get().rbegin(); + while (it != disconnectpool.queuedTx.get().rend()) { + // ignore validation errors in resurrected transactions + CValidationState stateDummy; + if (!fAddToMempool || (*it)->IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, *it, false, NULL, NULL, true)) { + // If the transaction doesn't make it in to the mempool, remove any + // transactions that depend on it (which would now be orphans). + mempool.removeRecursive(**it, MemPoolRemovalReason::REORG); + } else if (mempool.exists((*it)->GetHash())) { + vHashUpdate.push_back((*it)->GetHash()); + } + ++it; + } + disconnectpool.queuedTx.clear(); + // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have + // no in-mempool children, which is generally not true when adding + // previously-confirmed transactions back to the mempool. + // UpdateTransactionsFromBlock finds descendants of any transactions in + // the disconnectpool that were added back and cleans up the mempool state. + mempool.UpdateTransactionsFromBlock(vHashUpdate); + + // We also need to remove any now-immature transactions + mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); + // Re-limit mempool size, in case we added any transactions + LimitMempoolSize(mempool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); +} + static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree, - bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, - const CAmount& nAbsurdFee, std::vector& coins_to_uncache, bool fDryRun) + bool* pfMissingInputs, int64_t nAcceptTime, bool fOverrideMempoolLimit, + const CAmount& nAbsurdFee, std::vector& coins_to_uncache, bool fDryRun) { const CTransaction& tx = *ptx; const uint256 hash = tx.GetHash(); @@ -2517,8 +2567,17 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { LogPrintf("%s\n", strMessage); } -/** Disconnect chainActive's tip. You probably want to call mempool.removeForReorg and manually re-limit mempool size after this, with cs_main held. */ -bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams) +/** Disconnect chainActive's tip. + * After calling, the mempool will be in an inconsistent state, with + * transactions from disconnected blocks being added to disconnectpool. You + * should make the mempool consistent again by calling UpdateMempoolForReorg. + * with cs_main held. + * + * If disconnectpool is NULL, then no disconnected transactions are added to + * disconnectpool (note that the caller is responsible for mempool consistency + * in any case). + */ +bool static DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool) { CBlockIndex *pindexDelete = chainActive.Tip(); assert(pindexDelete); @@ -2543,24 +2602,20 @@ bool static DisconnectTip(CValidationState& state, const CChainParams& chainpara // Write the chain state to disk, if necessary. if (!FlushStateToDisk(chainparams, state, FLUSH_STATE_IF_NEEDED)) return false; - // Resurrect mempool transactions from the disconnected block. - std::vector vHashUpdate; - for (const auto& it : block.vtx) { - const CTransaction& tx = *it; - // ignore validation errors in resurrected transactions - CValidationState stateDummy; - if (tx.IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, it, false, NULL, true)) { - mempool.removeRecursive(tx, MemPoolRemovalReason::REORG); - } else if (mempool.exists(tx.GetHash())) { - vHashUpdate.push_back(tx.GetHash()); + + if (disconnectpool) { + // Save transactions to re-add to mempool at end of reorg + for (auto it = block.vtx.rbegin(); it != block.vtx.rend(); ++it) { + disconnectpool->addTransaction(*it); + } + while (disconnectpool->DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE * 1000) { + // Drop the earliest entry, and remove its children from the mempool. + auto it = disconnectpool->queuedTx.get().begin(); + mempool.removeRecursive(**it, MemPoolRemovalReason::REORG); + disconnectpool->removeEntry(it); } } - // AcceptToMemoryPool/addUnchecked all assume that new mempool entries have - // no in-mempool children, which is generally not true when adding - // previously-confirmed transactions back to the mempool. - // UpdateTransactionsFromBlock finds descendants of any transactions in this - // block that were added back and cleans up the mempool state. - mempool.UpdateTransactionsFromBlock(vHashUpdate); + // Update chainActive and related variables. UpdateTip(pindexDelete->pprev, chainparams); // Let wallets know transactions went from 1-confirmed to @@ -2646,7 +2701,7 @@ class ConnectTrace { * * The block is added to connectTrace if connection succeeds. */ -bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr& pblock, ConnectTrace& connectTrace) +bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) { assert(pindexNew->pprev == chainActive.Tip()); // Read block from disk. @@ -2691,6 +2746,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams, LogPrint(BCLog::BENCHMARK, " - Writing chainstate: %.2fms [%.2fs]\n", (nTime5 - nTime4) * 0.001, nTimeChainState * 0.000001); // Remove conflicting transactions from the mempool.; mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); + disconnectpool.removeForBlock(blockConnecting.vtx); // Update chainActive & related variables. UpdateTip(pindexNew, chainparams); @@ -2784,9 +2840,14 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c // Disconnect active blocks which are no longer in the best chain. bool fBlocksDisconnected = false; + DisconnectedBlockTransactions disconnectpool; while (chainActive.Tip() && chainActive.Tip() != pindexFork) { - if (!DisconnectTip(state, chainparams)) + if (!DisconnectTip(state, chainparams, &disconnectpool)) { + // This is likely a fatal error, but keep the mempool consistent, + // just in case. Only remove from the mempool in this case. + UpdateMempoolForReorg(disconnectpool, false); return false; + } fBlocksDisconnected = true; } @@ -2809,7 +2870,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c // Connect new blocks. BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { - if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr(), connectTrace)) { + if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr(), connectTrace, disconnectpool)) { if (state.IsInvalid()) { // The block violates a consensus rule. if (!state.CorruptionPossible()) @@ -2820,6 +2881,9 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c break; } else { // A system error occurred (disk space, database error, ...). + // Make the mempool consistent with the current tip, just in case + // any observers try to use it before shutdown. + UpdateMempoolForReorg(disconnectpool, false); return false; } } else { @@ -2834,8 +2898,9 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c } if (fBlocksDisconnected) { - mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); - LimitMempoolSize(mempool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); + // If any blocks were disconnected, disconnectpool may be non empty. Add + // any disconnected transactions back to the mempool. + UpdateMempoolForReorg(disconnectpool, true); } mempool.check(pcoinsTip); @@ -2996,6 +3061,7 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C pindexBestHeader = pindexBestHeader->pprev; } + DisconnectedBlockTransactions disconnectpool; while (chainActive.Contains(pindex)) { CBlockIndex *pindexWalk = chainActive.Tip(); pindexWalk->nStatus |= BLOCK_FAILED_CHILD; @@ -3003,8 +3069,10 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C setBlockIndexCandidates.erase(pindexWalk); // ActivateBestChain considers blocks already in chainActive // unconditionally valid already, so force disconnect away from it. - if (!DisconnectTip(state, chainparams)) { - mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); + if (!DisconnectTip(state, chainparams, &disconnectpool)) { + // It's probably hopeless to try to make the mempool consistent + // here if DisconnectTip failed, but we can try. + UpdateMempoolForReorg(disconnectpool, false); return false; } if (pindexWalk == pindexBestHeader) { @@ -3013,7 +3081,9 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C } } - LimitMempoolSize(mempool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); + // DisconnectTip will add transactions to disconnectpool; try to add these + // back to the mempool. + UpdateMempoolForReorg(disconnectpool, true); // The resulting new best tip may not be in setBlockIndexCandidates anymore, so // add it again. @@ -3026,7 +3096,6 @@ bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, C } InvalidChainFound(pindex); - mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); GetMainSignals().UpdatedBlockTip(chainActive.Tip(), NULL, IsInitialBlockDownload()); uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev); return true; diff --git a/src/validation.h b/src/validation.h index 0af8b91c4930..ba9a55e6ff19 100644 --- a/src/validation.h +++ b/src/validation.h @@ -72,6 +72,8 @@ static const unsigned int DEFAULT_DESCENDANT_LIMIT = 25; static const unsigned int DEFAULT_DESCENDANT_SIZE_LIMIT = 101; /** Default for -mempoolexpiry, expiration time for mempool transactions in hours */ static const unsigned int DEFAULT_MEMPOOL_EXPIRY = 336; +/** Maximum kilobytes for transactions to store for processing during reorg */ +static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE = 20000; /** The maximum size of a blk?????.dat file (since 0.8) */ static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB /** The pre-allocation chunk size for blk?????.dat files (since 0.8) */ diff --git a/test/functional/pruning.py b/test/functional/pruning.py index 18e79670957e..f499bdab820e 100755 --- a/test/functional/pruning.py +++ b/test/functional/pruning.py @@ -34,10 +34,11 @@ def __init__(self): # Create nodes 0 and 1 to mine. # Create node 2 to test pruning. + self.full_node_default_args = ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5", "-limitdescendantcount=100", "-limitdescendantsize=5000", "-limitancestorcount=100", "-limitancestorsize=5000" ] # Create nodes 3 and 4 to test manual pruning (they will be re-started with manual pruning later) # Create nodes 5 to test wallet in prune mode, but do not connect - self.extra_args = [["-maxreceivebuffer=20000", "-blockmaxsize=999000", "-checkblocks=5"], - ["-maxreceivebuffer=20000", "-blockmaxsize=999000", "-checkblocks=5"], + self.extra_args = [self.full_node_default_args, + self.full_node_default_args, ["-litemode","-txindex=0","-maxreceivebuffer=20000","-prune=550"], ["-litemode","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], ["-litemode","-txindex=0","-maxreceivebuffer=20000","-blockmaxsize=999000"], @@ -97,12 +98,15 @@ def create_chain_with_staleblocks(self): # Node 2 stays connected, so it hears about the stale blocks and then reorg's when node0 reconnects # Stopping node 0 also clears its mempool, so it doesn't have node1's transactions to accidentally mine self.stop_node(0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900) + self.nodes[0]=start_node(0, self.options.tmpdir, self.full_node_default_args, timewait=900) # Mine 24 blocks in node 1 for i in range(24): if j == 0: mine_large_block(self.nodes[1], self.utxo_cache_1) else: + # Add node1's wallet transactions back to the mempool, to + # avoid the mined blocks from being too small. + self.nodes[1].resendwallettransactions() self.nodes[1].generate(1) #tx's already in mempool from previous disconnects # Reorg back with 25 block chain from node 0 @@ -159,6 +163,11 @@ def reorg_test(self): self.log.info("Usage possibly still high bc of stale blocks in block files: %d" % calc_usage(self.prunedir)) self.log.info("Mine 220 more blocks so we have requisite history (some blocks will be big and cause pruning of previous chain)") + + # Get node0's wallet transactions back in its mempool, to avoid the + # mined blocks from being too small. + self.nodes[0].resendwallettransactions() + for i in range(22): # This can be slow, so do this in multiple RPC calls to avoid # RPC timeouts. From 1c6630f72fb4435ab7f8418a72a34041c68a7a1a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 30 May 2017 16:55:17 -0700 Subject: [PATCH 285/987] Merge #10464: Introduce static DoWarning (simplify UpdateTip) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit f28514576 Introduce static DoWarning (simplify UpdateTip) (Jorge Timón) Tree-SHA512: 58b39f00bc921d47d199ef1cc15e9e36f918ec86e9182de46dc2f24fa9474853a92b18d330a274a3ea7c9b001681fdfa3d86aa2bbebb5c92ac8c5a6f7690dfc1 --- src/validation.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index b981cef3aa38..e37291b937e6 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2505,6 +2505,16 @@ void PruneAndFlush() { FlushStateToDisk(chainparams, state, FLUSH_STATE_NONE); } +static void DoWarning(const std::string& strWarning) +{ + static bool fWarned = false; + SetMiscWarning(strWarning); + if (!fWarned) { + AlertNotify(strWarning); + fWarned = true; + } +} + /** Update chainActive and related internal data structures. */ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { chainActive.SetTip(pindexNew); @@ -2514,7 +2524,6 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { cvBlockChange.notify_all(); - static bool fWarned = false; std::vector warningMessages; if (!IsInitialBlockDownload()) { @@ -2524,15 +2533,11 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { WarningBitsConditionChecker checker(bit); ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]); if (state == THRESHOLD_ACTIVE || state == THRESHOLD_LOCKED_IN) { + const std::string strWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit); if (state == THRESHOLD_ACTIVE) { - std::string strWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit); - SetMiscWarning(strWarning); - if (!fWarned) { - AlertNotify(strWarning); - fWarned = true; - } + DoWarning(strWarning); } else { - warningMessages.push_back(strprintf("unknown new rules are about to activate (versionbit %i)", bit)); + warningMessages.push_back(strWarning); } } } @@ -2545,16 +2550,12 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { pindex = pindex->pprev; } if (nUpgraded > 0) - warningMessages.push_back(strprintf("%d of last 100 blocks have unexpected version", nUpgraded)); + warningMessages.push_back(strprintf(_("%d of last 100 blocks have unexpected version"), nUpgraded)); if (nUpgraded > 100/2) { std::string strWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect"); // notify GetWarnings(), called by Qt and the JSON-RPC code to warn the user: - SetMiscWarning(strWarning); - if (!fWarned) { - AlertNotify(strWarning); - fWarned = true; - } + DoWarning(strWarning); } } std::string strMessage = strprintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, From 3ee7ffc7fd4a1d50bff3cc1c4b143816b2b70b21 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 31 May 2017 17:15:38 +0200 Subject: [PATCH 286/987] Merge #10479: [trivial] Fix comment for ForceSetArg() 42a83e5 [trivial] Fix comment for ForceSetArg() (John Newbery) Tree-SHA512: 596db8b4bb01bca18908e254e5b364d3d4fcb0ea49d7d54314c65106e497efed65a877d80740bff88e090aeb772be1e46d4571ecca9b9263578f3f680f0bd0ce --- src/util.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util.h b/src/util.h index 61641d508b5e..e0299d1b2614 100644 --- a/src/util.h +++ b/src/util.h @@ -295,7 +295,8 @@ bool SoftSetArg(const std::string& strArg, const std::string& strValue); */ bool SoftSetBoolArg(const std::string& strArg, bool fValue); -// Forces a arg setting +// Forces an arg setting. Called by SoftSetArg() if the arg hasn't already +// been set. Also called directly in testing. void ForceSetArg(const std::string& strArg, const std::string& strValue); void ForceSetMultiArgs(const std::string& strArg, const std::vector& values); void ForceRemoveArg(const std::string& strArg); From 785420b838d77932a0b5597a73f3729f4eec72ce Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 31 May 2017 17:29:29 +0200 Subject: [PATCH 287/987] Merge #10467: add SeedNodes to CConnman::Options 5d67526 add SeedNodes to CConnman::Options (Marko Bencun) Tree-SHA512: d732ab08697419f896d9598fa3c30030ddbe3b82a99a398d813ebcd5e1fc610ad1043fe0f4c51a7ec5c4d70ce93a9ac5a5c7a91fcaae046ec4f1f7c41523a360 --- src/init.cpp | 9 ++++----- src/net.cpp | 8 ++++++-- src/net.h | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 86e2ce4ee76b..ac53bf2702b0 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1715,11 +1715,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } } - if (gArgs.IsArgSet("-seednode")) { - BOOST_FOREACH(const std::string& strDest, gArgs.GetArgs("-seednode")) - connman.AddOneShot(strDest); - } - #if ENABLE_ZMQ pzmqNotificationInterface = CZMQNotificationInterface::Create(); @@ -2146,6 +2141,10 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; connOptions.nMaxOutboundLimit = nMaxOutboundLimit; + if (gArgs.IsArgSet("-seednode")) { + connOptions.vSeedNodes = gArgs.GetArgs("-seednode"); + } + if (!connman.Start(scheduler, strNodeError, connOptions)) return InitError(strNodeError); diff --git a/src/net.cpp b/src/net.cpp index bb89fc422ed5..fb02012c2505 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1857,9 +1857,9 @@ void CConnman::ThreadOpenConnections() // * Increase the number of connectable addresses in the tried table. // // Method: - // * Choose a random address from new and attempt to connect to it if we can connect + // * Choose a random address from new and attempt to connect to it if we can connect // successfully it is added to tried. - // * Start attempting feeler connections only after node finishes making outbound + // * Start attempting feeler connections only after node finishes making outbound // connections. // * Only make a feeler connection once every few minutes. // @@ -2435,6 +2435,10 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c SetBestHeight(connOptions.nBestHeight); + for (const auto& strDest : connOptions.vSeedNodes) { + AddOneShot(strDest); + } + clientInterface = connOptions.uiInterface; if (clientInterface) { clientInterface->InitMessage(_("Loading P2P addresses...")); diff --git a/src/net.h b/src/net.h index b066c2887dfa..59b82277622a 100644 --- a/src/net.h +++ b/src/net.h @@ -167,6 +167,7 @@ class CConnman unsigned int nReceiveFloodSize = 0; uint64_t nMaxOutboundTimeframe = 0; uint64_t nMaxOutboundLimit = 0; + std::vector vSeedNodes; }; CConnman(uint64_t seed0, uint64_t seed1); ~CConnman(); @@ -362,8 +363,6 @@ class CConnman void GetBanned(banmap_t &banmap); void SetBanned(const banmap_t &banmap); - void AddOneShot(const std::string& strDest); - bool AddNode(const std::string& node); bool RemoveAddedNode(const std::string& node); std::vector GetAddedNodeInfo(); @@ -432,6 +431,7 @@ class CConnman }; void ThreadOpenAddedConnections(); + void AddOneShot(const std::string& strDest); void ProcessOneShot(); void ThreadOpenConnections(); void ThreadMessageHandler(); From 89e033085dc2d1156239e17909bae97c658473bd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 1 Jun 2017 10:50:22 +0200 Subject: [PATCH 288/987] Merge #10447: Make bitcoind invalid argument error message specific cd5622d Make bitcoind invalid argument error message specific (Wladimir J. van der Laan) Tree-SHA512: 78999b9359685c4090f9a112e1d02bdddac22173f5f04600773b042acb9481ebb54d0f73d9d6d74249f845f497927a58d59de69bf33e3dccf096c3c80c7ebf6b --- src/dashd.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/dashd.cpp b/src/dashd.cpp index 025387b95e9a..29331afb9b4c 100644 --- a/src/dashd.cpp +++ b/src/dashd.cpp @@ -125,17 +125,14 @@ bool AppInit(int argc, char* argv[]) return false; } - // Command-line RPC - bool fCommandLine = false; - for (int i = 1; i < argc; i++) - if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "dash:")) - fCommandLine = true; - - if (fCommandLine) - { - fprintf(stderr, "Error: There is no RPC client functionality in dashd anymore. Use the dash-cli utility instead.\n"); - exit(EXIT_FAILURE); + // Error out when loose non-argument tokens are encountered on command line + for (int i = 1; i < argc; i++) { + if (!IsSwitchChar(argv[i][0])) { + fprintf(stderr, "Error: Command line contains unexpected token '%s', see dashd -h for a list of options.\n", argv[i]); + exit(EXIT_FAILURE); + } } + // -server defaults to true for bitcoind but not for the GUI so do this here SoftSetBoolArg("-server", true); // Set this early so that parameter interactions go to console From 2ab30b846c5f4ba6d8774b2d3b68bae48e1e8432 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 1 Jun 2017 19:18:37 +0200 Subject: [PATCH 289/987] Merge #10475: [RPC] getmempoolinfo mempoolminfee is a BTC/KB feerate f128f78 getmempool mempoolminfee is a BTC/KB feerate (Gregory Sanders) Tree-SHA512: 5b32ffc0d2ba7ca623d4ce450fb67855d17b4fa8c3ffb8570a63dc53b3d476d52b39ad6190ac4357dbf01f6b535fa187cd8c34175a16469e9b00097e3bf2e2bc --- src/rpc/blockchain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 96463f5e9f9a..8c45ed5efe3f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1622,7 +1622,7 @@ UniValue getmempoolinfo(const JSONRPCRequest& request) " \"bytes\": xxxxx, (numeric) Sum of all tx sizes\n" " \"usage\": xxxxx, (numeric) Total memory usage for the mempool\n" " \"maxmempool\": xxxxx, (numeric) Maximum memory usage for the mempool\n" - " \"mempoolminfee\": xxxxx (numeric) Minimum fee for tx to be accepted\n" + " \"mempoolminfee\": xxxxx (numeric) Minimum feerate (" + CURRENCY_UNIT + " per KB) for tx to be accepted\n" "}\n" "\nExamples:\n" + HelpExampleCli("getmempoolinfo", "") From b62db761809d67f121f0460c87eab53ee835cf34 Mon Sep 17 00:00:00 2001 From: Pasta Date: Sun, 23 Jun 2019 11:30:23 -0500 Subject: [PATCH 290/987] Revert " Add real timestamp to log output when mock time is enabled (#2604)" This reverts commit 968eb3fc5d2a29420f21443a2acb6e65b1e4adea. Signed-off-by: Pasta # Conflicts: # src/util.cpp # src/utiltime.cpp # src/utiltime.h --- src/util.cpp | 6 +----- src/utiltime.cpp | 5 ----- src/utiltime.h | 1 - 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 0e51a46f8fe3..5e308664751d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -375,12 +375,8 @@ static std::string LogTimestampStr(const std::string &str, std::atomic_bool *fSt return str; if (*fStartedNewLine) { - if (IsMockTime()) { - int64_t nRealTimeMicros = GetTimeMicros(); - strStamped = DateTimeStrFormat("(real %Y-%m-%d %H:%M:%S) ", nRealTimeMicros/1000000); - } int64_t nTimeMicros = GetTimeMicros(); - strStamped += DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nTimeMicros/1000000); + strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nTimeMicros/1000000); if (fLogTimeMicros) strStamped += strprintf(".%06d", nTimeMicros%1000000); int64_t mocktime = GetMockTime(); diff --git a/src/utiltime.cpp b/src/utiltime.cpp index e18c6ebfd2ce..759df4865a9d 100644 --- a/src/utiltime.cpp +++ b/src/utiltime.cpp @@ -32,11 +32,6 @@ void SetMockTime(int64_t nMockTimeIn) nMockTime.store(nMockTimeIn, std::memory_order_relaxed); } -bool IsMockTime() -{ - return nMockTime != 0; -} - int64_t GetMockTime() { return nMockTime.load(std::memory_order_relaxed); diff --git a/src/utiltime.h b/src/utiltime.h index b4dc3b5dfa2e..8ae8540b89c7 100644 --- a/src/utiltime.h +++ b/src/utiltime.h @@ -24,7 +24,6 @@ int64_t GetTimeMillis(); int64_t GetTimeMicros(); int64_t GetSystemTimeInSeconds(); // Like GetTime(), but not mockable void SetMockTime(int64_t nMockTimeIn); -bool IsMockTime(); int64_t GetMockTime(); void MilliSleep(int64_t n); From bb370afbfd4534f92cbc52f9583ff2e057b7c3a0 Mon Sep 17 00:00:00 2001 From: Pasta Date: Sun, 23 Jun 2019 11:31:43 -0500 Subject: [PATCH 291/987] s/bitcoin/dash Signed-off-by: Pasta --- test/functional/test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index c1fe6d477cd6..854fa1f68432 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -204,7 +204,7 @@ def main(): logging.basicConfig(format='%(message)s', level=logging_level) # Create base test directory - tmpdir = "%s/bitcoin_test_runner_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S")) + tmpdir = "%s/dash_test_runner_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S")) os.makedirs(tmpdir) logging.debug("Temporary test directory at %s" % tmpdir) From 1bb4b9c08598cfb1f5db03984b8ffc7c85d6b69b Mon Sep 17 00:00:00 2001 From: Pasta Date: Sun, 23 Jun 2019 11:33:05 -0500 Subject: [PATCH 292/987] fix gargs change regarding devnets Signed-off-by: Pasta --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index ac53bf2702b0..c672000451c2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1114,7 +1114,7 @@ bool AppInitParameterInteraction() if (GetArg("-server", false) && !IsArgSet("-rpcport")) { return InitError(_("-rpcport must be specified when -devnet and -server are specified")); } - if (gArgs.IsArgSet("-devnet")) { + if (gArgs.GetArgs("-devnet").size() > 1) { return InitError(_("-devnet can only be specified once")); } } From 5bdb2c0ce1b48c9420594da243928a22b4d153ef Mon Sep 17 00:00:00 2001 From: Pasta Date: Sun, 23 Jun 2019 11:35:08 -0500 Subject: [PATCH 293/987] Revert "Show BIP9 progress in getblockchaininfo (#2435)" This reverts commit 3685c85e7f5b4fa3772e40765116ef7bfc85596e. --- src/rpc/blockchain.cpp | 15 --------------- src/versionbits.cpp | 20 -------------------- src/versionbits.h | 2 -- 3 files changed, 37 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 8c45ed5efe3f..e2cfae447baf 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1324,16 +1324,6 @@ static UniValue BIP9SoftForkDesc(const Consensus::Params& consensusParams, Conse if (THRESHOLD_STARTED == thresholdState) { rv.push_back(Pair("bit", consensusParams.vDeployments[id].bit)); - - int nBlockCount = VersionBitsCountBlocksInWindow(chainActive.Tip(), consensusParams, id); - int64_t nPeriod = consensusParams.vDeployments[id].nWindowSize ? consensusParams.vDeployments[id].nWindowSize : consensusParams.nMinerConfirmationWindow; - int64_t nThreshold = consensusParams.vDeployments[id].nThreshold ? consensusParams.vDeployments[id].nThreshold : consensusParams.nRuleChangeActivationThreshold; - int64_t nWindowStart = chainActive.Height() - (chainActive.Height() % nPeriod); - rv.push_back(Pair("period", nPeriod)); - rv.push_back(Pair("threshold", nThreshold)); - rv.push_back(Pair("windowStart", nWindowStart)); - rv.push_back(Pair("windowBlocks", nBlockCount)); - rv.push_back(Pair("windowProgress", std::min(1.0, (double)nBlockCount / nThreshold))); } rv.push_back(Pair("startTime", consensusParams.vDeployments[id].nStartTime)); rv.push_back(Pair("timeout", consensusParams.vDeployments[id].nTimeout)); @@ -1392,11 +1382,6 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) " \"xxxx\" : { (string) name of the softfork\n" " \"status\": \"xxxx\", (string) one of \"defined\", \"started\", \"locked_in\", \"active\", \"failed\"\n" " \"bit\": xx, (numeric) the bit (0-28) in the block version field used to signal this softfork (only for \"started\" status)\n" - " \"period\": xx, (numeric) the window size/period for this softfork (only for \"started\" status)\n" - " \"threshold\": xx, (numeric) the threshold for this softfork (only for \"started\" status)\n" - " \"windowStart\": xx, (numeric) the starting block height of the current window (only for \"started\" status)\n" - " \"windowBlocks\": xx, (numeric) the number of blocks in the current window that had the version bit set for this softfork (only for \"started\" status)\n" - " \"windowProgress\": xx, (numeric) the progress (between 0 and 1) for activation of this softfork (only for \"started\" status)\n" " \"startTime\": xx, (numeric) the minimum median time past of a block at which the bit gains its meaning\n" " \"timeout\": xx, (numeric) the median time past of a block at which the deployment is considered failed if not yet locked in\n" " \"since\": xx, (numeric) height of the first block to which the status applies\n" diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 1cd282a7ca67..f7bf5f81dccc 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -182,21 +182,6 @@ int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* return pindexPrev->nHeight + 1; } -int AbstractThresholdConditionChecker::CountBlocksInWindow(const CBlockIndex* pindex, const Consensus::Params& params) const -{ - int nPeriod = Period(params); - int nStopHeight = pindex->nHeight - (pindex->nHeight % nPeriod) - 1; - const CBlockIndex* pindexCount = pindex; - int count = 0; - while (pindexCount && pindexCount->nHeight != nStopHeight) { - if (Condition(pindexCount, params)) { - count++; - } - pindexCount = pindexCount->pprev; - } - return count; -} - namespace { /** @@ -239,11 +224,6 @@ int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus:: return VersionBitsConditionChecker(pos).GetStateSinceHeightFor(pindexPrev, params, cache.caches[pos]); } -int VersionBitsCountBlocksInWindow(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos) -{ - return VersionBitsConditionChecker(pos).CountBlocksInWindow(pindex, params); -} - uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos) { return VersionBitsConditionChecker(pos).Mask(params); diff --git a/src/versionbits.h b/src/versionbits.h index 1ff944a89bd9..7e5f5b1e4539 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -65,7 +65,6 @@ class AbstractThresholdConditionChecker { // Note that the functions below take a pindexPrev as input: they compute information for block B based on its parent. ThresholdState GetStateFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const; int GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const; - int CountBlocksInWindow(const CBlockIndex* pindex, const Consensus::Params& params) const; }; struct VersionBitsCache @@ -78,7 +77,6 @@ struct VersionBitsCache ThresholdState VersionBitsState(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); BIP9Stats VersionBitsStatistics(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos); int VersionBitsStateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos, VersionBitsCache& cache); -int VersionBitsCountBlocksInWindow(const CBlockIndex* pindex, const Consensus::Params& params, Consensus::DeploymentPos pos); uint32_t VersionBitsMask(const Consensus::Params& params, Consensus::DeploymentPos pos); #endif From 6bfbe6053dd1df4565fdde49f87bd0f4e5c3cb11 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 24 Jun 2019 11:44:27 -0500 Subject: [PATCH 294/987] Scripted diff `find src/ -name "*.cpp" ! -wholename "src/util.h" ! -wholename "src/util.cpp" | xargs perl -i -pe 's/(? --- src/chainparamsbase.cpp | 10 +- src/dash-cli.cpp | 34 +-- src/dash-tx.cpp | 10 +- src/dashd.cpp | 18 +- src/dbwrapper.cpp | 2 +- src/httprpc.cpp | 4 +- src/httpserver.cpp | 14 +- src/init.cpp | 290 ++++++++++++------------- src/keepass.cpp | 10 +- src/llmq/quorums.cpp | 2 +- src/llmq/quorums_dkgsessionhandler.cpp | 2 +- src/llmq/quorums_signing.cpp | 2 +- src/miner.cpp | 12 +- src/net.cpp | 10 +- src/net_processing.cpp | 16 +- src/policy/fees.cpp | 2 +- src/qt/bitcoingui.cpp | 2 +- src/qt/dash.cpp | 20 +- src/qt/guiutil.cpp | 6 +- src/qt/intro.cpp | 8 +- src/qt/optionsmodel.cpp | 30 +-- src/qt/paymentrequestplus.cpp | 2 +- src/qt/paymentserver.cpp | 2 +- src/qt/rpcconsole.cpp | 2 +- src/qt/splashscreen.cpp | 6 +- src/qt/test/rpcnestedtests.cpp | 2 +- src/qt/utilitydialog.cpp | 2 +- src/qt/walletmodel.cpp | 2 +- src/rpc/blockchain.cpp | 6 +- src/rpc/protocol.cpp | 2 +- src/rpc/server.cpp | 2 +- src/script/sigcache.cpp | 2 +- src/test/DoS_tests.cpp | 4 +- src/test/getarg_tests.cpp | 112 +++++----- src/test/miner_tests.cpp | 2 +- src/test/net_tests.cpp | 2 +- src/test/pow_tests.cpp | 2 +- src/test/test_dash.cpp | 2 +- src/timedata.cpp | 2 +- src/torcontrol.cpp | 6 +- src/txmempool.cpp | 2 +- src/validation.cpp | 32 +-- src/wallet/db.cpp | 4 +- src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.cpp | 124 +++++------ src/wallet/walletdb.cpp | 4 +- src/warnings.cpp | 2 +- src/zmq/zmqnotificationinterface.cpp | 4 +- 48 files changed, 420 insertions(+), 420 deletions(-) diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 9353f7772e79..57f1d8deb826 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -120,9 +120,9 @@ void SelectBaseParams(const std::string& chain) std::string ChainNameFromCommandLine() { - bool fRegTest = GetBoolArg("-regtest", false); - bool fDevNet = IsArgSet("-devnet"); - bool fTestNet = GetBoolArg("-testnet", false); + bool fRegTest = gArgs.GetBoolArg("-regtest", false); + bool fDevNet = gArgs.IsArgSet("-devnet"); + bool fTestNet = gArgs.GetBoolArg("-testnet", false); int nameParamsCount = (fRegTest ? 1 : 0) + (fDevNet ? 1 : 0) + (fTestNet ? 1 : 0); if (nameParamsCount > 1) @@ -140,7 +140,7 @@ std::string ChainNameFromCommandLine() std::string GetDevNetName() { // This function should never be called for non-devnets - assert(IsArgSet("-devnet")); - std::string devNetName = GetArg("-devnet", ""); + assert(gArgs.IsArgSet("-devnet")); + std::string devNetName = gArgs.GetArg("-devnet", ""); return "devnet" + (devNetName.empty() ? "" : "-" + devNetName); } diff --git a/src/dash-cli.cpp b/src/dash-cli.cpp index 26c6da8be679..ea45e9ed5717 100644 --- a/src/dash-cli.cpp +++ b/src/dash-cli.cpp @@ -78,10 +78,10 @@ static int AppInitRPC(int argc, char* argv[]) // // Parameters // - ParseParameters(argc, argv); - if (argc<2 || IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help") || IsArgSet("-version")) { + gArgs.ParseParameters(argc, argv); + if (argc<2 || gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") || gArgs.IsArgSet("-help") || gArgs.IsArgSet("-version")) { std::string strUsage = strprintf(_("%s RPC client version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n"; - if (!IsArgSet("-version")) { + if (!gArgs.IsArgSet("-version")) { strUsage += "\n" + _("Usage:") + "\n" + " dash-cli [options] [params] " + strprintf(_("Send command to %s"), _(PACKAGE_NAME)) + "\n" + " dash-cli [options] -named [name=value] ... " + strprintf(_("Send command to %s (with named arguments)"), _(PACKAGE_NAME)) + "\n" + @@ -98,19 +98,19 @@ static int AppInitRPC(int argc, char* argv[]) } return EXIT_SUCCESS; } - bool datadirFromCmdLine = IsArgSet("-datadir"); + bool datadirFromCmdLine = gArgs.IsArgSet("-datadir"); if (datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { - fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str()); + fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); return EXIT_FAILURE; } try { - ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)); + gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); } catch (const std::exception& e) { fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return EXIT_FAILURE; } if (!datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { - fprintf(stderr, "Error: Specified data directory \"%s\" from config file does not exist.\n", GetArg("-datadir", "").c_str()); + fprintf(stderr, "Error: Specified data directory \"%s\" from config file does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); return EXIT_FAILURE; } // Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause) @@ -120,7 +120,7 @@ static int AppInitRPC(int argc, char* argv[]) fprintf(stderr, "Error: %s\n", e.what()); return EXIT_FAILURE; } - if (GetBoolArg("-rpcssl", false)) + if (gArgs.GetBoolArg("-rpcssl", false)) { fprintf(stderr, "Error: SSL mode for RPC (-rpcssl) is no longer supported.\n"); return EXIT_FAILURE; @@ -196,15 +196,15 @@ static void http_error_cb(enum evhttp_request_error err, void *ctx) UniValue CallRPC(const std::string& strMethod, const UniValue& params) { - std::string host = GetArg("-rpcconnect", DEFAULT_RPCCONNECT); - int port = GetArg("-rpcport", BaseParams().RPCPort()); + std::string host = gArgs.GetArg("-rpcconnect", DEFAULT_RPCCONNECT); + int port = gArgs.GetArg("-rpcport", BaseParams().RPCPort()); // Obtain event base raii_event_base base = obtain_event_base(); // Synchronously look up hostname raii_evhttp_connection evcon = obtain_evhttp_connection_base(base.get(), host, port); - evhttp_connection_set_timeout(evcon.get(), GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT)); + evhttp_connection_set_timeout(evcon.get(), gArgs.GetArg("-rpcclienttimeout", DEFAULT_HTTP_CLIENT_TIMEOUT)); HTTPReply response; raii_evhttp_request req = obtain_evhttp_request(http_request_done, (void*)&response); @@ -216,16 +216,16 @@ UniValue CallRPC(const std::string& strMethod, const UniValue& params) // Get credentials std::string strRPCUserColonPass; - if (GetArg("-rpcpassword", "") == "") { + if (gArgs.GetArg("-rpcpassword", "") == "") { // Try fall back to cookie-based authentication if no password is provided if (!GetAuthCookie(&strRPCUserColonPass)) { throw std::runtime_error(strprintf( _("Could not locate RPC credentials. No authentication cookie could be found, and no rpcpassword is set in the configuration file (%s)"), - GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str())); + GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str())); } } else { - strRPCUserColonPass = GetArg("-rpcuser", "") + ":" + GetArg("-rpcpassword", ""); + strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", ""); } struct evkeyvalq* output_headers = evhttp_request_get_output_headers(req.get()); @@ -279,7 +279,7 @@ int CommandLineRPC(int argc, char *argv[]) argv++; } std::vector args = std::vector(&argv[1], &argv[argc]); - if (GetBoolArg("-stdin", false)) { + if (gArgs.GetBoolArg("-stdin", false)) { // Read one arg per line from stdin and append std::string line; while (std::getline(std::cin,line)) @@ -291,14 +291,14 @@ int CommandLineRPC(int argc, char *argv[]) args.erase(args.begin()); // Remove trailing method name from arguments vector UniValue params; - if(GetBoolArg("-named", DEFAULT_NAMED)) { + if(gArgs.GetBoolArg("-named", DEFAULT_NAMED)) { params = RPCConvertNamedValues(strMethod, args); } else { params = RPCConvertValues(strMethod, args); } // Execute and handle connection failures with -rpcwait - const bool fWait = GetBoolArg("-rpcwait", false); + const bool fWait = gArgs.GetBoolArg("-rpcwait", false); do { try { const UniValue reply = CallRPC(strMethod, params); diff --git a/src/dash-tx.cpp b/src/dash-tx.cpp index e93a003842a6..d5dd5e3f2b74 100644 --- a/src/dash-tx.cpp +++ b/src/dash-tx.cpp @@ -41,7 +41,7 @@ static int AppInitRawTx(int argc, char* argv[]) // // Parameters // - ParseParameters(argc, argv); + gArgs.ParseParameters(argc, argv); // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) try { @@ -51,9 +51,9 @@ static int AppInitRawTx(int argc, char* argv[]) return EXIT_FAILURE; } - fCreateBlank = GetBoolArg("-create", false); + fCreateBlank = gArgs.GetBoolArg("-create", false); - if (argc<2 || IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help")) + if (argc<2 || gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") || gArgs.IsArgSet("-help")) { // First part of help message is specific to this utility std::string strUsage = strprintf(_("%s dash-tx utility version"), _(PACKAGE_NAME)) + " " + FormatFullVersion() + "\n\n" + @@ -675,9 +675,9 @@ static void OutputTxHex(const CTransaction& tx) static void OutputTx(const CTransaction& tx) { - if (GetBoolArg("-json", false)) + if (gArgs.GetBoolArg("-json", false)) OutputTxJSON(tx); - else if (GetBoolArg("-txid", false)) + else if (gArgs.GetBoolArg("-txid", false)) OutputTxHash(tx); else OutputTxHex(tx); diff --git a/src/dashd.cpp b/src/dashd.cpp index 29331afb9b4c..e8359b622494 100644 --- a/src/dashd.cpp +++ b/src/dashd.cpp @@ -74,14 +74,14 @@ bool AppInit(int argc, char* argv[]) // Parameters // // If Qt is used, parameters/dash.conf are parsed in qt/dash.cpp's main() - ParseParameters(argc, argv); + gArgs.ParseParameters(argc, argv); // Process help and version before taking care about datadir - if (IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help") || IsArgSet("-version")) + if (gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") || gArgs.IsArgSet("-help") || gArgs.IsArgSet("-version")) { std::string strUsage = strprintf(_("%s Daemon"), _(PACKAGE_NAME)) + " " + _("version") + " " + FormatFullVersion() + "\n"; - if (IsArgSet("-version")) + if (gArgs.IsArgSet("-version")) { strUsage += FormatParagraph(LicenseInfo()); } @@ -99,22 +99,22 @@ bool AppInit(int argc, char* argv[]) try { - bool datadirFromCmdLine = IsArgSet("-datadir"); + bool datadirFromCmdLine = gArgs.IsArgSet("-datadir"); if (datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { - fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "").c_str()); + fprintf(stderr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); return false; } try { - ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)); + gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); } catch (const std::exception& e) { fprintf(stderr,"Error reading configuration file: %s\n", e.what()); return false; } if (!datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) { - fprintf(stderr, "Error: Specified data directory \"%s\" from config file does not exist.\n", GetArg("-datadir", "").c_str()); + fprintf(stderr, "Error: Specified data directory \"%s\" from config file does not exist.\n", gArgs.GetArg("-datadir", "").c_str()); return EXIT_FAILURE; } // Check for -testnet or -regtest parameter (Params() calls are only valid after this clause) @@ -134,7 +134,7 @@ bool AppInit(int argc, char* argv[]) } // -server defaults to true for bitcoind but not for the GUI so do this here - SoftSetBoolArg("-server", true); + gArgs.SoftSetBoolArg("-server", true); // Set this early so that parameter interactions go to console InitLogging(); InitParameterInteraction(); @@ -153,7 +153,7 @@ bool AppInit(int argc, char* argv[]) // InitError will have been called with detailed error, which ends up on console exit(EXIT_FAILURE); } - if (GetBoolArg("-daemon", false)) + if (gArgs.GetBoolArg("-daemon", false)) { #if HAVE_DECL_DAEMON fprintf(stdout, "Dash Core server starting\n"); diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 2538ea0ce372..638d669c4c0a 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -115,7 +115,7 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo dbwrapper_private::HandleError(status); LogPrintf("Opened LevelDB successfully\n"); - if (GetBoolArg("-forcecompactdb", false)) { + if (gArgs.GetBoolArg("-forcecompactdb", false)) { LogPrintf("Starting database compaction of %s\n", path.string()); pdb->CompactRange(nullptr, nullptr); LogPrintf("Finished database compaction of %s\n", path.string()); diff --git a/src/httprpc.cpp b/src/httprpc.cpp index df2fb9aae7f4..3c4389bdd912 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -215,7 +215,7 @@ static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &) static bool InitRPCAuthentication() { - if (GetArg("-rpcpassword", "") == "") + if (gArgs.GetArg("-rpcpassword", "") == "") { LogPrintf("No rpcpassword set - using random cookie authentication\n"); if (!GenerateAuthCookie(&strRPCUserColonPass)) { @@ -226,7 +226,7 @@ static bool InitRPCAuthentication() } } else { LogPrintf("Config options rpcuser and rpcpassword will soon be deprecated. Locally-run instances may remove rpcuser to use cookie-based auth, or may be replaced with rpcauth. Please see share/rpcuser for rpcauth auth generation.\n"); - strRPCUserColonPass = GetArg("-rpcuser", "") + ":" + GetArg("-rpcpassword", ""); + strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + gArgs.GetArg("-rpcpassword", ""); } return true; } diff --git a/src/httpserver.cpp b/src/httpserver.cpp index e81a6d89ecd1..7b8c21c9a649 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -311,14 +311,14 @@ static bool ThreadHTTP(struct event_base* base, struct evhttp* http) /** Bind HTTP server to specified addresses */ static bool HTTPBindAddresses(struct evhttp* http) { - int defaultPort = GetArg("-rpcport", BaseParams().RPCPort()); + int defaultPort = gArgs.GetArg("-rpcport", BaseParams().RPCPort()); std::vector > endpoints; // Determine what addresses to bind to - if (!IsArgSet("-rpcallowip")) { // Default to loopback if not allowing external IPs + if (!gArgs.IsArgSet("-rpcallowip")) { // Default to loopback if not allowing external IPs endpoints.push_back(std::make_pair("::1", defaultPort)); endpoints.push_back(std::make_pair("127.0.0.1", defaultPort)); - if (IsArgSet("-rpcbind")) { + if (gArgs.IsArgSet("-rpcbind")) { LogPrintf("WARNING: option -rpcbind was ignored because -rpcallowip was not specified, refusing to allow everyone to connect\n"); } } else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address @@ -375,7 +375,7 @@ bool InitHTTPServer() if (!InitHTTPAllowList()) return false; - if (GetBoolArg("-rpcssl", false)) { + if (gArgs.GetBoolArg("-rpcssl", false)) { uiInterface.ThreadSafeMessageBox( "SSL mode for RPC (-rpcssl) is no longer supported.", "", CClientUIInterface::MSG_ERROR); @@ -411,7 +411,7 @@ bool InitHTTPServer() return false; } - evhttp_set_timeout(http, GetArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT)); + evhttp_set_timeout(http, gArgs.GetArg("-rpcservertimeout", DEFAULT_HTTP_SERVER_TIMEOUT)); evhttp_set_max_headers_size(http, MAX_HEADERS_SIZE); evhttp_set_max_body_size(http, MAX_SIZE); evhttp_set_gencb(http, http_request_cb, NULL); @@ -424,7 +424,7 @@ bool InitHTTPServer() } LogPrint(BCLog::HTTP, "Initialized HTTP server\n"); - int workQueueDepth = std::max((long)GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L); + int workQueueDepth = std::max((long)gArgs.GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L); LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth); workQueue = new WorkQueue(workQueueDepth); @@ -453,7 +453,7 @@ std::future threadResult; bool StartHTTPServer() { LogPrint(BCLog::HTTP, "Starting HTTP server\n"); - int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L); + int rpcThreads = std::max((long)gArgs.GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L); LogPrintf("HTTP: starting %d worker threads\n", rpcThreads); std::packaged_task task(ThreadHTTP); threadResult = task.get_future(); diff --git a/src/init.cpp b/src/init.cpp index c672000451c2..73039b1dad72 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -277,7 +277,7 @@ void PrepareShutdown() } UnregisterNodeSignals(GetNodeSignals()); - if (fDumpMempoolLater && GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { + if (fDumpMempoolLater && gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { DumpMempool(); } @@ -427,14 +427,14 @@ void OnRPCPreCommand(const CRPCCommand& cmd) { // Observe safe mode std::string strWarning = GetWarnings("rpc"); - if (strWarning != "" && !GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE) && + if (strWarning != "" && !gArgs.GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE) && !cmd.okSafeMode) throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, std::string("Safe mode: ") + strWarning); } std::string HelpMessage(HelpMessageMode mode) { - const bool showDebug = GetBoolArg("-help-debug", false); + const bool showDebug = gArgs.GetBoolArg("-help-debug", false); // When adding new options to the categories, please keep and ensure alphabetical ordering. // Do not translate _(...) -help-debug options, Many technical terms, and only a very small audience, so is unnecessary stress to translators. @@ -681,7 +681,7 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex if (initialSync || !pBlockIndex) return; - std::string strCmd = GetArg("-blocknotify", ""); + std::string strCmd = gArgs.GetArg("-blocknotify", ""); boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex()); boost::thread t(runCommand, strCmd); // thread runs free @@ -818,7 +818,7 @@ void ThreadImport(std::vector vImportFiles) StartShutdown(); } - if (GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { + if (gArgs.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { LogPrintf("Stopping after block import\n"); StartShutdown(); } @@ -841,7 +841,7 @@ void ThreadImport(std::vector vImportFiles) } #endif - if (GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { + if (gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { LoadMempool(); fDumpMempoolLater = !fRequestShutdown; } @@ -884,7 +884,7 @@ bool AppInitServers(boost::thread_group& threadGroup) return false; if (!StartHTTPRPC()) return false; - if (GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST()) + if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST()) return false; if (!StartHTTPServer()) return false; @@ -896,93 +896,93 @@ void InitParameterInteraction() { // when specifying an explicit binding address, you want to listen on it // even when -connect or -proxy is specified - if (IsArgSet("-bind")) { - if (SoftSetBoolArg("-listen", true)) + if (gArgs.IsArgSet("-bind")) { + if (gArgs.SoftSetBoolArg("-listen", true)) LogPrintf("%s: parameter interaction: -bind set -> setting -listen=1\n", __func__); } - if (IsArgSet("-whitebind")) { - if (SoftSetBoolArg("-listen", true)) + if (gArgs.IsArgSet("-whitebind")) { + if (gArgs.SoftSetBoolArg("-listen", true)) LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__); } - if (GetBoolArg("-masternode", false)) { + if (gArgs.GetBoolArg("-masternode", false)) { // masternodes MUST accept connections from outside - ForceSetArg("-listen", "1"); + gArgs.ForceSetArg("-listen", "1"); LogPrintf("%s: parameter interaction: -masternode=1 -> setting -listen=1\n", __func__); - if (GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) < DEFAULT_MAX_PEER_CONNECTIONS) { + if (gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) < DEFAULT_MAX_PEER_CONNECTIONS) { // masternodes MUST be able to handle at least DEFAULT_MAX_PEER_CONNECTIONS connections - ForceSetArg("-maxconnections", itostr(DEFAULT_MAX_PEER_CONNECTIONS)); + gArgs.ForceSetArg("-maxconnections", itostr(DEFAULT_MAX_PEER_CONNECTIONS)); LogPrintf("%s: parameter interaction: -masternode=1 -> setting -maxconnections=%d\n", __func__, DEFAULT_MAX_PEER_CONNECTIONS); } } if (gArgs.IsArgSet("-connect")) { // when only connecting to trusted nodes, do not seed via DNS, or listen by default - if (SoftSetBoolArg("-dnsseed", false)) + if (gArgs.SoftSetBoolArg("-dnsseed", false)) LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__); - if (SoftSetBoolArg("-listen", false)) + if (gArgs.SoftSetBoolArg("-listen", false)) LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__); } - if (IsArgSet("-proxy")) { + if (gArgs.IsArgSet("-proxy")) { // to protect privacy, do not listen by default if a default proxy server is specified - if (SoftSetBoolArg("-listen", false)) + if (gArgs.SoftSetBoolArg("-listen", false)) LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__); // to protect privacy, do not use UPNP when a proxy is set. The user may still specify -listen=1 // to listen locally, so don't rely on this happening through -listen below. - if (SoftSetBoolArg("-upnp", false)) + if (gArgs.SoftSetBoolArg("-upnp", false)) LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__); // to protect privacy, do not discover addresses by default - if (SoftSetBoolArg("-discover", false)) + if (gArgs.SoftSetBoolArg("-discover", false)) LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__); } - if (!GetBoolArg("-listen", DEFAULT_LISTEN)) { + if (!gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) { // do not map ports or try to retrieve public IP when not listening (pointless) - if (SoftSetBoolArg("-upnp", false)) + if (gArgs.SoftSetBoolArg("-upnp", false)) LogPrintf("%s: parameter interaction: -listen=0 -> setting -upnp=0\n", __func__); - if (SoftSetBoolArg("-discover", false)) + if (gArgs.SoftSetBoolArg("-discover", false)) LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__); - if (SoftSetBoolArg("-listenonion", false)) + if (gArgs.SoftSetBoolArg("-listenonion", false)) LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__); } - if (IsArgSet("-externalip")) { + if (gArgs.IsArgSet("-externalip")) { // if an explicit public IP is specified, do not try to find others - if (SoftSetBoolArg("-discover", false)) + if (gArgs.SoftSetBoolArg("-discover", false)) LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__); } // disable whitelistrelay in blocksonly mode - if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) { - if (SoftSetBoolArg("-whitelistrelay", false)) + if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) { + if (gArgs.SoftSetBoolArg("-whitelistrelay", false)) LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__); } // Forcing relay from whitelisted hosts implies we will accept relays from them in the first place. - if (GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) { - if (SoftSetBoolArg("-whitelistrelay", true)) + if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) { + if (gArgs.SoftSetBoolArg("-whitelistrelay", true)) LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n", __func__); } #ifdef ENABLE_WALLET - int nLiqProvTmp = GetArg("-liquidityprovider", DEFAULT_PRIVATESEND_LIQUIDITY); + int nLiqProvTmp = gArgs.GetArg("-liquidityprovider", DEFAULT_PRIVATESEND_LIQUIDITY); if (nLiqProvTmp > 0) { - ForceSetArg("-enableprivatesend", "1"); + gArgs.ForceSetArg("-enableprivatesend", "1"); LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -enableprivatesend=1\n", __func__, nLiqProvTmp); - ForceSetArg("-privatesendsessions", itostr(MIN_PRIVATESEND_SESSIONS)); + gArgs.ForceSetArg("-privatesendsessions", itostr(MIN_PRIVATESEND_SESSIONS)); LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendsessions=%d\n", __func__, nLiqProvTmp, itostr(std::numeric_limits::max())); - ForceSetArg("-privatesendrounds", itostr(std::numeric_limits::max())); + gArgs.ForceSetArg("-privatesendrounds", itostr(std::numeric_limits::max())); LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendrounds=%d\n", __func__, nLiqProvTmp, itostr(std::numeric_limits::max())); - ForceSetArg("-privatesendamount", itostr(MAX_PRIVATESEND_AMOUNT)); + gArgs.ForceSetArg("-privatesendamount", itostr(MAX_PRIVATESEND_AMOUNT)); LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendamount=%d\n", __func__, nLiqProvTmp, MAX_PRIVATESEND_AMOUNT); - ForceSetArg("-privatesenddenoms", itostr(MAX_PRIVATESEND_DENOMS)); + gArgs.ForceSetArg("-privatesenddenoms", itostr(MAX_PRIVATESEND_DENOMS)); LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesenddenoms=%d\n", __func__, nLiqProvTmp, itostr(MAX_PRIVATESEND_DENOMS)); - ForceSetArg("-privatesendmultisession", "0"); + gArgs.ForceSetArg("-privatesendmultisession", "0"); LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendmultisession=0\n", __func__, nLiqProvTmp); } - if (IsArgSet("-hdseed") && IsHex(GetArg("-hdseed", "not hex")) && (IsArgSet("-mnemonic") || IsArgSet("-mnemonicpassphrase"))) { + if (gArgs.IsArgSet("-hdseed") && IsHex(gArgs.GetArg("-hdseed", "not hex")) && (gArgs.IsArgSet("-mnemonic") || gArgs.IsArgSet("-mnemonicpassphrase"))) { ForceRemoveArg("-mnemonic"); ForceRemoveArg("-mnemonicpassphrase"); LogPrintf("%s: parameter interaction: can't use -hdseed and -mnemonic/-mnemonicpassphrase together, will prefer -seed\n", __func__); @@ -992,12 +992,12 @@ void InitParameterInteraction() // Make sure additional indexes are recalculated correctly in VerifyDB // (we must reconnect blocks whenever we disconnect them for these indexes to work) bool fAdditionalIndexes = - GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX) || - GetBoolArg("-spentindex", DEFAULT_SPENTINDEX) || - GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX); + gArgs.GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX) || + gArgs.GetBoolArg("-spentindex", DEFAULT_SPENTINDEX) || + gArgs.GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX); - if (fAdditionalIndexes && GetArg("-checklevel", DEFAULT_CHECKLEVEL) < 4) { - ForceSetArg("-checklevel", "4"); + if (fAdditionalIndexes && gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL) < 4) { + gArgs.ForceSetArg("-checklevel", "4"); LogPrintf("%s: parameter interaction: additional indexes -> setting -checklevel=4\n", __func__); } } @@ -1009,12 +1009,12 @@ static std::string ResolveErrMsg(const char * const optname, const std::string& void InitLogging() { - fPrintToConsole = GetBoolArg("-printtoconsole", false); - fPrintToDebugLog = GetBoolArg("-printtodebuglog", true) && !fPrintToConsole; - fLogTimestamps = GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS); - fLogTimeMicros = GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS); - fLogThreadNames = GetBoolArg("-logthreadnames", DEFAULT_LOGTHREADNAMES); - fLogIPs = GetBoolArg("-logips", DEFAULT_LOGIPS); + fPrintToConsole = gArgs.GetBoolArg("-printtoconsole", false); + fPrintToDebugLog = gArgs.GetBoolArg("-printtodebuglog", true) && !fPrintToConsole; + fLogTimestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS); + fLogTimeMicros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS); + fLogThreadNames = gArgs.GetBoolArg("-logthreadnames", DEFAULT_LOGTHREADNAMES); + fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS); LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); LogPrintf("Dash Core version %s\n", FormatFullVersion()); @@ -1073,7 +1073,7 @@ bool AppInitBasicSetup() return InitError("Initializing networking failed"); #ifndef WIN32 - if (!GetBoolArg("-sysperms", false)) { + if (!gArgs.GetBoolArg("-sysperms", false)) { umask(077); } @@ -1101,17 +1101,17 @@ bool AppInitParameterInteraction() // also see: InitParameterInteraction() // if using block pruning, then disallow txindex - if (GetArg("-prune", 0)) { - if (GetBoolArg("-txindex", DEFAULT_TXINDEX)) + if (gArgs.GetArg("-prune", 0)) { + if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) return InitError(_("Prune mode is incompatible with -txindex.")); } - if (IsArgSet("-devnet")) { + if (gArgs.IsArgSet("-devnet")) { // Require setting of ports when running devnet - if (GetArg("-listen", DEFAULT_LISTEN) && !IsArgSet("-port")) { + if (gArgs.GetArg("-listen", DEFAULT_LISTEN) && !gArgs.IsArgSet("-port")) { return InitError(_("-port must be specified when -devnet and -listen are specified")); } - if (GetArg("-server", false) && !IsArgSet("-rpcport")) { + if (gArgs.GetArg("-server", false) && !gArgs.IsArgSet("-rpcport")) { return InitError(_("-rpcport must be specified when -devnet and -server are specified")); } if (gArgs.GetArgs("-devnet").size() > 1) { @@ -1119,13 +1119,13 @@ bool AppInitParameterInteraction() } } - fAllowPrivateNet = GetBoolArg("-allowprivatenet", DEFAULT_ALLOWPRIVATENET); + fAllowPrivateNet = gArgs.GetBoolArg("-allowprivatenet", DEFAULT_ALLOWPRIVATENET); // Make sure enough file descriptors are available int nBind = std::max( (gArgs.IsArgSet("-bind") ? gArgs.GetArgs("-bind").size() : 0) + (gArgs.IsArgSet("-whitebind") ? gArgs.GetArgs("-whitebind").size() : 0), size_t(1)); - nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); + nUserMaxConnections = gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); nMaxConnections = std::max(nUserMaxConnections, 0); // Trim requested connection counts, to fit into system limitations @@ -1144,7 +1144,7 @@ bool AppInitParameterInteraction() // Special-case: if -debug=0/-nodebug is set, turn off debugging messages const std::vector categories = gArgs.GetArgs("-debug"); - if (!(GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), std::string("0")) != categories.end())) { + if (!(gArgs.GetBoolArg("-nodebug", false) || find(categories.begin(), categories.end(), std::string("0")) != categories.end())) { for (const auto& cat : categories) { uint64_t flag; if (!GetLogCategory(&flag, &cat)) { @@ -1167,55 +1167,55 @@ bool AppInitParameterInteraction() } // Check for -debugnet - if (GetBoolArg("-debugnet", false)) + if (gArgs.GetBoolArg("-debugnet", false)) InitWarning(_("Unsupported argument -debugnet ignored, use -debug=net.")); // Check for -socks - as this is a privacy risk to continue, exit here - if (IsArgSet("-socks")) + if (gArgs.IsArgSet("-socks")) return InitError(_("Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported.")); // Check for -tor - as this is a privacy risk to continue, exit here - if (GetBoolArg("-tor", false)) + if (gArgs.GetBoolArg("-tor", false)) return InitError(_("Unsupported argument -tor found, use -onion.")); - if (GetBoolArg("-benchmark", false)) + if (gArgs.GetBoolArg("-benchmark", false)) InitWarning(_("Unsupported argument -benchmark ignored, use -debug=bench.")); - if (GetBoolArg("-whitelistalwaysrelay", false)) + if (gArgs.GetBoolArg("-whitelistalwaysrelay", false)) InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use -whitelistrelay and/or -whitelistforcerelay.")); - if (IsArgSet("-blockminsize")) + if (gArgs.IsArgSet("-blockminsize")) InitWarning("Unsupported argument -blockminsize ignored."); // Checkmempool and checkblockindex default to true in regtest mode - int ratio = std::min(std::max(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); + int ratio = std::min(std::max(gArgs.GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000); if (ratio != 0) { mempool.setSanityCheck(1.0 / ratio); } - fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); - fCheckpointsEnabled = GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED); + fCheckBlockIndex = gArgs.GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks()); + fCheckpointsEnabled = gArgs.GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED); - hashAssumeValid = uint256S(GetArg("-assumevalid", chainparams.GetConsensus().defaultAssumeValid.GetHex())); + hashAssumeValid = uint256S(gArgs.GetArg("-assumevalid", chainparams.GetConsensus().defaultAssumeValid.GetHex())); if (!hashAssumeValid.IsNull()) LogPrintf("Assuming ancestors of block %s have valid signatures.\n", hashAssumeValid.GetHex()); else LogPrintf("Validating signatures for all blocks.\n"); // mempool limits - int64_t nMempoolSizeMax = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; - int64_t nMempoolSizeMin = GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40; + int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; + int64_t nMempoolSizeMin = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40; if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(nMempoolSizeMin / 1000000.0))); // incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool // and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting. - if (IsArgSet("-incrementalrelayfee")) + if (gArgs.IsArgSet("-incrementalrelayfee")) { CAmount n = 0; - if (!ParseMoney(GetArg("-incrementalrelayfee", ""), n)) - return InitError(AmountErrMsg("incrementalrelayfee", GetArg("-incrementalrelayfee", ""))); + if (!ParseMoney(gArgs.GetArg("-incrementalrelayfee", ""), n)) + return InitError(AmountErrMsg("incrementalrelayfee", gArgs.GetArg("-incrementalrelayfee", ""))); incrementalRelayFee = CFeeRate(n); } // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency - nScriptCheckThreads = GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS); + nScriptCheckThreads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS); if (nScriptCheckThreads <= 0) nScriptCheckThreads += GetNumCores(); if (nScriptCheckThreads <= 1) @@ -1224,7 +1224,7 @@ bool AppInitParameterInteraction() nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS; // block pruning; get the amount of disk space (in MiB) to allot for block & undo files - int64_t nPruneArg = GetArg("-prune", 0); + int64_t nPruneArg = gArgs.GetArg("-prune", 0); if (nPruneArg < 0) { return InitError(_("Prune cannot be configured with a negative value.")); } @@ -1234,7 +1234,7 @@ bool AppInitParameterInteraction() nPruneTarget = std::numeric_limits::max(); fPruneMode = true; } else if (nPruneTarget) { - if (GetBoolArg("-regtest", false)) { + if (gArgs.GetBoolArg("-regtest", false)) { // we use 1MB blocks to test this on regtest if (nPruneTarget < 550 * 1024 * 1024) { return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), 550)); @@ -1253,7 +1253,7 @@ bool AppInitParameterInteraction() RegisterWalletRPCCommands(tableRPC); #endif - nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); + nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); if (nConnectTimeout <= 0) nConnectTimeout = DEFAULT_CONNECT_TIMEOUT; @@ -1263,11 +1263,11 @@ bool AppInitParameterInteraction() // a transaction spammer can cheaply fill blocks using // 0-fee transactions. It should be set above the real // cost to you of processing a transaction. - if (IsArgSet("-minrelaytxfee")) + if (gArgs.IsArgSet("-minrelaytxfee")) { CAmount n = 0; - if (!ParseMoney(GetArg("-minrelaytxfee", ""), n)) { - return InitError(AmountErrMsg("minrelaytxfee", GetArg("-minrelaytxfee", ""))); + if (!ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n)) { + return InitError(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", ""))); } // High fee check is done afterward in CWallet::ParameterInteraction() ::minRelayTxFee = CFeeRate(n); @@ -1279,44 +1279,44 @@ bool AppInitParameterInteraction() // Sanity check argument for min fee for including tx in block // TODO: Harmonize which arguments need sanity checking and where that happens - if (IsArgSet("-blockmintxfee")) + if (gArgs.IsArgSet("-blockmintxfee")) { CAmount n = 0; - if (!ParseMoney(GetArg("-blockmintxfee", ""), n)) - return InitError(AmountErrMsg("blockmintxfee", GetArg("-blockmintxfee", ""))); + if (!ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) + return InitError(AmountErrMsg("blockmintxfee", gArgs.GetArg("-blockmintxfee", ""))); } // Feerate used to define dust. Shouldn't be changed lightly as old // implementations may inadvertently create non-standard transactions - if (IsArgSet("-dustrelayfee")) + if (gArgs.IsArgSet("-dustrelayfee")) { CAmount n = 0; - if (!ParseMoney(GetArg("-dustrelayfee", ""), n) || 0 == n) - return InitError(AmountErrMsg("dustrelayfee", GetArg("-dustrelayfee", ""))); + if (!ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n) || 0 == n) + return InitError(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", ""))); dustRelayFee = CFeeRate(n); } - fRequireStandard = !GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard()); + fRequireStandard = !gArgs.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard()); if (chainparams.RequireStandard() && !fRequireStandard) return InitError(strprintf("acceptnonstdtxn is not currently supported for %s chain", chainparams.NetworkIDString())); - nBytesPerSigOp = GetArg("-bytespersigop", nBytesPerSigOp); + nBytesPerSigOp = gArgs.GetArg("-bytespersigop", nBytesPerSigOp); #ifdef ENABLE_WALLET if (!CWallet::ParameterInteraction()) return false; #endif // ENABLE_WALLET - fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG); - fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER); - nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes); + fIsBareMultisigStd = gArgs.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG); + fAcceptDatacarrier = gArgs.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER); + nMaxDatacarrierBytes = gArgs.GetArg("-datacarriersize", nMaxDatacarrierBytes); // Option to startup with mocktime set (used for regression testing): - SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op + SetMockTime(gArgs.GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op - if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) + if (gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM); - nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE); + nMaxTipAge = gArgs.GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE); if (gArgs.IsArgSet("-bip9params")) { // Allow overriding BIP9 parameters for testing @@ -1360,12 +1360,12 @@ bool AppInitParameterInteraction() } } - if (IsArgSet("-dip3params")) { + if (gArgs.IsArgSet("-dip3params")) { // Allow overriding budget parameters for testing if (!chainparams.MineBlocksOnDemand()) { return InitError("DIP3 parameters may only be overridden on regtest."); } - std::string strDIP3Params = GetArg("-dip3params", ""); + std::string strDIP3Params = gArgs.GetArg("-dip3params", ""); std::vector vDIP3Params; boost::split(vDIP3Params, strDIP3Params, boost::is_any_of(":")); if (vDIP3Params.size() != 2) { @@ -1381,13 +1381,13 @@ bool AppInitParameterInteraction() UpdateRegtestDIP3Parameters(nDIP3ActivationHeight, nDIP3EnforcementHeight); } - if (IsArgSet("-budgetparams")) { + if (gArgs.IsArgSet("-budgetparams")) { // Allow overriding budget parameters for testing if (!chainparams.MineBlocksOnDemand()) { return InitError("Budget parameters may only be overridden on regtest."); } - std::string strBudgetParams = GetArg("-budgetparams", ""); + std::string strBudgetParams = gArgs.GetArg("-budgetparams", ""); std::vector vBudgetParams; boost::split(vBudgetParams, strBudgetParams, boost::is_any_of(":")); if (vBudgetParams.size() != 3) { @@ -1407,16 +1407,16 @@ bool AppInitParameterInteraction() } if (chainparams.NetworkIDString() == CBaseChainParams::DEVNET) { - int nMinimumDifficultyBlocks = GetArg("-minimumdifficultyblocks", chainparams.GetConsensus().nMinimumDifficultyBlocks); - int nHighSubsidyBlocks = GetArg("-highsubsidyblocks", chainparams.GetConsensus().nHighSubsidyBlocks); - int nHighSubsidyFactor = GetArg("-highsubsidyfactor", chainparams.GetConsensus().nHighSubsidyFactor); + int nMinimumDifficultyBlocks = gArgs.GetArg("-minimumdifficultyblocks", chainparams.GetConsensus().nMinimumDifficultyBlocks); + int nHighSubsidyBlocks = gArgs.GetArg("-highsubsidyblocks", chainparams.GetConsensus().nHighSubsidyBlocks); + int nHighSubsidyFactor = gArgs.GetArg("-highsubsidyfactor", chainparams.GetConsensus().nHighSubsidyFactor); UpdateDevnetSubsidyAndDiffParams(nMinimumDifficultyBlocks, nHighSubsidyBlocks, nHighSubsidyFactor); - } else if (IsArgSet("-minimumdifficultyblocks") || IsArgSet("-highsubsidyblocks") || IsArgSet("-highsubsidyfactor")) { + } else if (gArgs.IsArgSet("-minimumdifficultyblocks") || gArgs.IsArgSet("-highsubsidyblocks") || gArgs.IsArgSet("-highsubsidyfactor")) { return InitError("Difficulty and subsidy parameters may only be overridden on devnet."); } if (chainparams.NetworkIDString() == CBaseChainParams::DEVNET) { - std::string llmqChainLocks = GetArg("-llmqchainlocks", Params().GetConsensus().llmqs.at(Params().GetConsensus().llmqChainLocks).name); + std::string llmqChainLocks = gArgs.GetArg("-llmqchainlocks", Params().GetConsensus().llmqs.at(Params().GetConsensus().llmqChainLocks).name); Consensus::LLMQType llmqType = Consensus::LLMQ_NONE; for (const auto& p : Params().GetConsensus().llmqs) { if (p.second.name == llmqChainLocks) { @@ -1428,7 +1428,7 @@ bool AppInitParameterInteraction() return InitError("Invalid LLMQ type specified for -llmqchainlocks."); } UpdateDevnetLLMQChainLocks(llmqType); - } else if (IsArgSet("-llmqchainlocks")) { + } else if (gArgs.IsArgSet("-llmqchainlocks")) { return InitError("LLMQ type for ChainLocks can only be overridden on devnet."); } @@ -1489,7 +1489,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) #ifndef WIN32 CreatePidFile(GetPidFile(), getpid()); #endif - if (GetBoolArg("-shrinkdebugfile", logCategories == BCLog::NONE)) { + if (gArgs.GetBoolArg("-shrinkdebugfile", logCategories == BCLog::NONE)) { // Do this first since it both loads a bunch of debug.log into memory, // and because this needs to happen before any other debug.log printing ShrinkDebugFile(); @@ -1502,7 +1502,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime())); LogPrintf("Default data directory %s\n", GetDefaultDataDir().string()); LogPrintf("Using data directory %s\n", GetDataDir().string()); - LogPrintf("Using config file %s\n", GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)).string()); + LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string()); LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD); InitSignatureCache(); @@ -1525,14 +1525,14 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } } - int minsporkkeys = GetArg("-minsporkkeys", Params().MinSporkKeys()); + int minsporkkeys = gArgs.GetArg("-minsporkkeys", Params().MinSporkKeys()); if (!sporkManager.SetMinSporkKeys(minsporkkeys)) { return InitError(_("Invalid minimum number of spork signers specified with -minsporkkeys")); } - if (IsArgSet("-sporkkey")) { // spork priv key - if (!sporkManager.SetPrivKey(GetArg("-sporkkey", ""))) { + if (gArgs.IsArgSet("-sporkkey")) { // spork priv key + if (!sporkManager.SetPrivKey(gArgs.GetArg("-sporkkey", ""))) { return InitError(_("Unable to sign spork message, wrong key?")); } } @@ -1546,7 +1546,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) * that the server is there and will be ready later). Warmup mode will * be disabled when initialisation is finished. */ - if (GetBoolArg("-server", false)) + if (gArgs.GetBoolArg("-server", false)) { uiInterface.InitMessage.connect(SetRPCWarmupStatus); if (!AppInitServers(threadGroup)) @@ -1626,12 +1626,12 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } // Check for host lookup allowed before parsing any network related parameters - fNameLookup = GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); + fNameLookup = gArgs.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); - bool proxyRandomize = GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE); + bool proxyRandomize = gArgs.GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE); // -proxy sets a proxy for all outgoing network traffic // -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default - std::string proxyArg = GetArg("-proxy", ""); + std::string proxyArg = gArgs.GetArg("-proxy", ""); SetLimited(NET_TOR); if (proxyArg != "" && proxyArg != "0") { CService proxyAddr; @@ -1653,7 +1653,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses // -noonion (or -onion=0) disables connecting to .onion entirely // An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none) - std::string onionArg = GetArg("-onion", ""); + std::string onionArg = gArgs.GetArg("-onion", ""); if (onionArg != "") { if (onionArg == "0") { // Handle -noonion/-onion=0 SetLimited(NET_TOR); // set onions as unreachable @@ -1671,9 +1671,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } // see Step 2: parameter interactions for more information about these - fListen = GetBoolArg("-listen", DEFAULT_LISTEN); - fDiscover = GetBoolArg("-discover", true); - fRelayTxes = !GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); + fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN); + fDiscover = gArgs.GetBoolArg("-discover", true); + fRelayTxes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY); if (fListen) { bool fBound = false; @@ -1729,14 +1729,14 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set uint64_t nMaxOutboundTimeframe = MAX_UPLOAD_TIMEFRAME; - if (IsArgSet("-maxuploadtarget")) { - nMaxOutboundLimit = GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024; + if (gArgs.IsArgSet("-maxuploadtarget")) { + nMaxOutboundLimit = gArgs.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET)*1024*1024; } // ********************************************************* Step 7a: check lite mode and load sporks // lite mode disables all Dash-specific functionality - fLiteMode = GetBoolArg("-litemode", false); + fLiteMode = gArgs.GetBoolArg("-litemode", false); LogPrintf("fLiteMode %d\n", fLiteMode); if(fLiteMode) { @@ -1758,23 +1758,23 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 7b: load block chain - fReindex = GetBoolArg("-reindex", false); - bool fReindexChainState = GetBoolArg("-reindex-chainstate", false); + fReindex = gArgs.GetBoolArg("-reindex", false); + bool fReindexChainState = gArgs.GetBoolArg("-reindex-chainstate", false); fs::create_directories(GetDataDir() / "blocks"); // cache size calculations - int64_t nTotalCache = (GetArg("-dbcache", nDefaultDbCache) << 20); + int64_t nTotalCache = (gArgs.GetArg("-dbcache", nDefaultDbCache) << 20); nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greater than nMaxDbcache int64_t nBlockTreeDBCache = nTotalCache / 8; - nBlockTreeDBCache = std::min(nBlockTreeDBCache, (GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxBlockDBAndTxIndexCache : nMaxBlockDBCache) << 20); + nBlockTreeDBCache = std::min(nBlockTreeDBCache, (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxBlockDBAndTxIndexCache : nMaxBlockDBCache) << 20); nTotalCache -= nBlockTreeDBCache; int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache nTotalCache -= nCoinDBCache; nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache - int64_t nMempoolSizeMax = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; + int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; int64_t nEvoDbCache = 1024 * 1024 * 16; // TODO LogPrintf("Cache configuration:\n"); LogPrintf("* Using %.1fMiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024)); @@ -1844,7 +1844,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } // Check for changed -txindex state - if (fTxIndex != GetBoolArg("-txindex", DEFAULT_TXINDEX)) { + if (fTxIndex != gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { strLoadError = _("You need to rebuild the database using -reindex-chainstate to change -txindex"); break; } @@ -1857,7 +1857,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } uiInterface.InitMessage(_("Verifying blocks...")); - if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) { + if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) { LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks", MIN_BLOCKS_TO_KEEP); } @@ -1874,8 +1874,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } } - if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, GetArg("-checklevel", DEFAULT_CHECKLEVEL), - GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { + if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview, gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), + gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { strLoadError = _("Corrupted block database detected"); break; } @@ -1947,7 +1947,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } // ********************************************************* Step 10a: Prepare Masternode related stuff - fMasternodeMode = GetBoolArg("-masternode", false); + fMasternodeMode = gArgs.GetBoolArg("-masternode", false); // TODO: masternode should have no wallet if(fLiteMode && fMasternodeMode) { @@ -1957,7 +1957,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) if(fMasternodeMode) { LogPrintf("MASTERNODE:\n"); - std::string strMasterNodeBLSPrivKey = GetArg("-masternodeblsprivkey", ""); + std::string strMasterNodeBLSPrivKey = gArgs.GetArg("-masternodeblsprivkey", ""); if(!strMasterNodeBLSPrivKey.empty()) { auto binKey = ParseHex(strMasterNodeBLSPrivKey); CBLSSecretKey keyOperator; @@ -1988,7 +1988,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 10b: setup PrivateSend #ifdef ENABLE_WALLET - privateSendClient.nLiquidityProvider = std::min(std::max((int)GetArg("-liquidityprovider", DEFAULT_PRIVATESEND_LIQUIDITY), MIN_PRIVATESEND_LIQUIDITY), MAX_PRIVATESEND_LIQUIDITY); + privateSendClient.nLiquidityProvider = std::min(std::max((int)gArgs.GetArg("-liquidityprovider", DEFAULT_PRIVATESEND_LIQUIDITY), MIN_PRIVATESEND_LIQUIDITY), MAX_PRIVATESEND_LIQUIDITY); int nMaxRounds = MAX_PRIVATESEND_ROUNDS; if(privateSendClient.nLiquidityProvider) { // special case for liquidity providers only, normal clients should use default value @@ -1996,12 +1996,12 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) nMaxRounds = std::numeric_limits::max(); } - privateSendClient.fEnablePrivateSend = GetBoolArg("-enableprivatesend", false); - privateSendClient.fPrivateSendMultiSession = GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION); - privateSendClient.nPrivateSendSessions = std::min(std::max((int)GetArg("-privatesendsessions", DEFAULT_PRIVATESEND_SESSIONS), MIN_PRIVATESEND_SESSIONS), MAX_PRIVATESEND_SESSIONS); - privateSendClient.nPrivateSendRounds = std::min(std::max((int)GetArg("-privatesendrounds", DEFAULT_PRIVATESEND_ROUNDS), MIN_PRIVATESEND_ROUNDS), nMaxRounds); - privateSendClient.nPrivateSendAmount = std::min(std::max((int)GetArg("-privatesendamount", DEFAULT_PRIVATESEND_AMOUNT), MIN_PRIVATESEND_AMOUNT), MAX_PRIVATESEND_AMOUNT); - privateSendClient.nPrivateSendDenoms = std::min(std::max((int)GetArg("-privatesenddenoms", DEFAULT_PRIVATESEND_DENOMS), MIN_PRIVATESEND_DENOMS), MAX_PRIVATESEND_DENOMS); + privateSendClient.fEnablePrivateSend = gArgs.GetBoolArg("-enableprivatesend", false); + privateSendClient.fPrivateSendMultiSession = gArgs.GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION); + privateSendClient.nPrivateSendSessions = std::min(std::max((int)gArgs.GetArg("-privatesendsessions", DEFAULT_PRIVATESEND_SESSIONS), MIN_PRIVATESEND_SESSIONS), MAX_PRIVATESEND_SESSIONS); + privateSendClient.nPrivateSendRounds = std::min(std::max((int)gArgs.GetArg("-privatesendrounds", DEFAULT_PRIVATESEND_ROUNDS), MIN_PRIVATESEND_ROUNDS), nMaxRounds); + privateSendClient.nPrivateSendAmount = std::min(std::max((int)gArgs.GetArg("-privatesendamount", DEFAULT_PRIVATESEND_AMOUNT), MIN_PRIVATESEND_AMOUNT), MAX_PRIVATESEND_AMOUNT); + privateSendClient.nPrivateSendDenoms = std::min(std::max((int)gArgs.GetArg("-privatesenddenoms", DEFAULT_PRIVATESEND_DENOMS), MIN_PRIVATESEND_DENOMS), MAX_PRIVATESEND_DENOMS); LogPrintf("PrivateSend liquidityprovider: %d\n", privateSendClient.nLiquidityProvider); LogPrintf("PrivateSend rounds: %d\n", privateSendClient.nPrivateSendRounds); @@ -2013,7 +2013,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) // ********************************************************* Step 10b: setup InstantSend - fEnableInstantSend = GetBoolArg("-enableinstantsend", 1); + fEnableInstantSend = gArgs.GetBoolArg("-enableinstantsend", 1); // ********************************************************* Step 10c: Load cache data @@ -2091,7 +2091,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) fHaveGenesis = true; } - if (IsArgSet("-blocknotify")) + if (gArgs.IsArgSet("-blocknotify")) uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); std::vector vImportFiles; @@ -2117,13 +2117,13 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) //// debug print LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size()); LogPrintf("chainActive.Height() = %d\n", chainActive.Height()); - if (GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) + if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) StartTorControl(threadGroup, scheduler); Discover(threadGroup); // Map ports with UPnP - MapPort(GetBoolArg("-upnp", DEFAULT_UPNP)); + MapPort(gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)); std::string strNodeError; CConnman::Options connOptions; @@ -2135,8 +2135,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) connOptions.nMaxFeeler = 1; connOptions.nBestHeight = chainActive.Height(); connOptions.uiInterface = &uiInterface; - connOptions.nSendBufferMaxSize = 1000*GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); - connOptions.nReceiveFloodSize = 1000*GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); + connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); + connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe; connOptions.nMaxOutboundLimit = nMaxOutboundLimit; diff --git a/src/keepass.cpp b/src/keepass.cpp index 3a5d25c8cba8..539fd1ba44ce 100644 --- a/src/keepass.cpp +++ b/src/keepass.cpp @@ -101,11 +101,11 @@ CKeePassIntegrator::CKeePassIntegrator() // Initialze from application context void CKeePassIntegrator::init() { - bIsActive = GetBoolArg("-keepass", false); - nPort = GetArg("-keepassport", DEFAULT_KEEPASS_HTTP_PORT); - sKeyBase64 = SecureString(GetArg("-keepasskey", "").c_str()); - strKeePassId = GetArg("-keepassid", ""); - strKeePassEntryName = GetArg("-keepassname", ""); + bIsActive = gArgs.GetBoolArg("-keepass", false); + nPort = gArgs.GetArg("-keepassport", DEFAULT_KEEPASS_HTTP_PORT); + sKeyBase64 = SecureString(gArgs.GetArg("-keepasskey", "").c_str()); + strKeePassId = gArgs.GetArg("-keepassid", ""); + strKeePassEntryName = gArgs.GetArg("-keepassname", ""); // Convert key if available if(sKeyBase64.size() > 0) { diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index d3063ad9f54d..ba5b90eb5991 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -186,7 +186,7 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const connmanQuorumsToDelete.erase(curDkgBlock); for (auto& quorum : lastQuorums) { - if (!quorum->IsMember(myProTxHash) && !GetBoolArg("-watchquorums", DEFAULT_WATCH_QUORUMS)) { + if (!quorum->IsMember(myProTxHash) && !gArgs.GetBoolArg("-watchquorums", DEFAULT_WATCH_QUORUMS)) { continue; } diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index c1b4bafe92ed..b54561ccf9e6 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -467,7 +467,7 @@ void CDKGSessionHandler::HandleDKGRound() return changed; }); - if (curSession->AreWeMember() || GetBoolArg("-watchquorums", DEFAULT_WATCH_QUORUMS)) { + if (curSession->AreWeMember() || gArgs.GetBoolArg("-watchquorums", DEFAULT_WATCH_QUORUMS)) { std::set connections; if (curSession->AreWeMember()) { connections = CLLMQUtils::GetQuorumConnections(params.type, curQuorumHash, curSession->myProTxHash); diff --git a/src/llmq/quorums_signing.cpp b/src/llmq/quorums_signing.cpp index a070ff84d6c0..119812030c07 100644 --- a/src/llmq/quorums_signing.cpp +++ b/src/llmq/quorums_signing.cpp @@ -687,7 +687,7 @@ void CSigningManager::Cleanup() return; } - int64_t maxAge = GetArg("-recsigsmaxage", DEFAULT_MAX_RECOVERED_SIGS_AGE); + int64_t maxAge = gArgs.GetArg("-recsigsmaxage", DEFAULT_MAX_RECOVERED_SIGS_AGE); db.CleanupOldRecoveredSigs(maxAge); db.CleanupOldVotes(maxAge); diff --git a/src/miner.cpp b/src/miner.cpp index b0e2f0da3c60..0b4f37b34c5b 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -86,12 +86,12 @@ static BlockAssembler::Options DefaultOptions(const CChainParams& params) // Block resource limits BlockAssembler::Options options; options.nBlockMaxSize = DEFAULT_BLOCK_MAX_SIZE; - if (IsArgSet("-blockmaxsize")) { - options.nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); + if (gArgs.IsArgSet("-blockmaxsize")) { + options.nBlockMaxSize = gArgs.GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); } - if (IsArgSet("-blockmintxfee")) { + if (gArgs.IsArgSet("-blockmintxfee")) { CAmount n = 0; - ParseMoney(GetArg("-blockmintxfee", ""), n); + ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n); options.blockMinFeeRate = CFeeRate(n); } else { options.blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); @@ -143,7 +143,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc // -regtest only: allow overriding block.nVersion with // -blockversion=N to test forking scenarios if (chainparams.MineBlocksOnDemand()) - pblock->nVersion = GetArg("-blockversion", pblock->nVersion); + pblock->nVersion = gArgs.GetArg("-blockversion", pblock->nVersion); pblock->nTime = GetAdjustedTime(); const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); @@ -295,7 +295,7 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) nFees += iter->GetFee(); inBlock.insert(iter); - bool fPrintPriority = GetBoolArg("-printpriority", DEFAULT_PRINTPRIORITY); + bool fPrintPriority = gArgs.GetBoolArg("-printpriority", DEFAULT_PRINTPRIORITY); if (fPrintPriority) { LogPrintf("fee %s txid %s\n", CFeeRate(iter->GetModifiedFee(), iter->GetTxSize()).ToString(), diff --git a/src/net.cpp b/src/net.cpp index fb02012c2505..4923120058f9 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -104,7 +104,7 @@ void CConnman::AddOneShot(const std::string& strDest) unsigned short GetListenPort() { - return (unsigned short)(GetArg("-port", Params().GetDefaultPort())); + return (unsigned short)(gArgs.GetArg("-port", Params().GetDefaultPort())); } // find 'best' local address for a particular peer @@ -504,7 +504,7 @@ void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t ba banEntry.banReason = banReason; if (bantimeoffset <= 0) { - bantimeoffset = GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME); + bantimeoffset = gArgs.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME); sinceUnixEpoch = false; } banEntry.nBanUntil = (sinceUnixEpoch ? 0 : GetTime() )+bantimeoffset; @@ -1664,7 +1664,7 @@ void CConnman::ThreadDNSAddressSeed() // creating fewer identifying DNS requests, reduces trust by giving seeds // less influence on the network topology, and reduces traffic to the seeds. if ((addrman.size() > 0) && - (!GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) { + (!gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) { if (!interruptNet.sleep_for(std::chrono::seconds(11))) return; @@ -2042,7 +2042,7 @@ void CConnman::ThreadOpenAddedConnections() void CConnman::ThreadOpenMasternodeConnections() { // Connecting to specific addresses, no masternode connections available - if (IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0) + if (gArgs.IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0) return; while (!interruptNet) @@ -2523,7 +2523,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c // Send and receive from sockets, accept connections threadSocketHandler = std::thread(&TraceThread >, "net", std::function(std::bind(&CConnman::ThreadSocketHandler, this))); - if (!GetBoolArg("-dnsseed", true)) + if (!gArgs.GetBoolArg("-dnsseed", true)) LogPrintf("DNS seeding disabled\n"); else threadDNSAddressSeed = std::thread(&TraceThread >, "dnsseed", std::function(std::bind(&CConnman::ThreadDNSAddressSeed, this))); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 84328ba46b22..2fadd8abad13 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -631,7 +631,7 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals) void AddToCompactExtraTransactions(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) { - size_t max_extra_txn = GetArg("-blockreconstructionextratxn", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN); + size_t max_extra_txn = gArgs.GetArg("-blockreconstructionextratxn", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN); if (max_extra_txn <= 0) return; if (!vExtraTxnForCompact.size()) @@ -757,7 +757,7 @@ void Misbehaving(NodeId pnode, int howmuch) return; state->nMisbehavior += howmuch; - int banscore = GetArg("-banscore", DEFAULT_BANSCORE_THRESHOLD); + int banscore = gArgs.GetArg("-banscore", DEFAULT_BANSCORE_THRESHOLD); if (state->nMisbehavior >= banscore && state->nMisbehavior - howmuch < banscore) { LogPrintf("%s: %s peer=%d (%d -> %d) BAN THRESHOLD EXCEEDED\n", __func__, state->name, pnode, state->nMisbehavior-howmuch, state->nMisbehavior); @@ -1413,7 +1413,7 @@ inline void static SendBlockTransactions(const CBlock& block, const BlockTransac bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CConnman& connman, const std::atomic& interruptMsgProc) { LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->GetId()); - if (IsArgSet("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 0)) == 0) + if (gArgs.IsArgSet("-dropmessagestest") && GetRand(gArgs.GetArg("-dropmessagestest", 0)) == 0) { LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n"); return true; @@ -1699,7 +1699,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::QSENDRECSIGS, true)); } - if (GetBoolArg("-watchquorums", llmq::DEFAULT_WATCH_QUORUMS)) { + if (gArgs.GetBoolArg("-watchquorums", llmq::DEFAULT_WATCH_QUORUMS)) { connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::QWATCH)); } @@ -1810,7 +1810,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr bool fBlocksOnly = !fRelayTxes; // Allow whitelisted peers to send data other than blocks in blocks only mode if whitelistrelay is true - if (pfrom->fWhitelisted && GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) + if (pfrom->fWhitelisted && gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) fBlocksOnly = false; LOCK(cs_main); @@ -2095,7 +2095,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr { // Stop processing the transaction early if // We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off - if (!fRelayTxes && (!pfrom->fWhitelisted || !GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))) + if (!fRelayTxes && (!pfrom->fWhitelisted || !gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY))) { LogPrint(BCLog::NET, "transaction sent in violation of protocol peer=%d\n", pfrom->GetId()); return true; @@ -2290,7 +2290,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr AddOrphanTx(ptx, pfrom->GetId()); // DoS prevention: do not allow mapOrphanTransactions to grow unbounded - unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); + unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, gArgs.GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx); if (nEvicted > 0) { LogPrint(BCLog::MEMPOOL, "mapOrphan overflow, removed %u tx\n", nEvicted); @@ -2323,7 +2323,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr connman.RelayTransaction(tx); } - if (pfrom->fWhitelisted && GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) { + if (pfrom->fWhitelisted && gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) { // Always relay transactions received from whitelisted peers, even // if they were already in the mempool or rejected from it due // to policy, allowing the node to function as a gateway for diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 41e0e5393844..0b1759a5bbd2 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -564,7 +564,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, int *answerFoun *answerFoundAtTarget = confTarget - 1; // If mempool is limiting txs , return at least the min feerate from the mempool - CAmount minPoolFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(); + CAmount minPoolFee = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFeePerK(); if (minPoolFee > 0 && minPoolFee > median) return CFeeRate(minPoolFee); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b8d5790388aa..2c0ab0e950a6 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -144,7 +144,7 @@ BitcoinGUI::BitcoinGUI(const PlatformStyle *_platformStyle, const NetworkStyle * } else { windowTitle += tr("Node"); } - QString userWindowTitle = QString::fromStdString(GetArg("-windowtitle", "")); + QString userWindowTitle = QString::fromStdString(gArgs.GetArg("-windowtitle", "")); if(!userWindowTitle.isEmpty()) windowTitle += " - " + userWindowTitle; windowTitle += " " + networkStyle->getTitleAddText(); #ifndef Q_OS_MAC diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp index 4cd47236c964..c13163c409cc 100644 --- a/src/qt/dash.cpp +++ b/src/qt/dash.cpp @@ -109,7 +109,7 @@ static QString GetLangTerritory() if(!lang_territory_qsettings.isEmpty()) lang_territory = lang_territory_qsettings; // 3) -lang command line argument - lang_territory = QString::fromStdString(GetArg("-lang", lang_territory.toStdString())); + lang_territory = QString::fromStdString(gArgs.GetArg("-lang", lang_territory.toStdString())); return lang_territory; } @@ -361,7 +361,7 @@ BitcoinApplication::BitcoinApplication(int &argc, char **argv): // This must be done inside the BitcoinApplication constructor, or after it, because // PlatformStyle::instantiate requires a QApplication std::string platformName; - platformName = GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM); + platformName = gArgs.GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM); platformStyle = PlatformStyle::instantiate(QString::fromStdString(platformName)); if (!platformStyle) // Fall back to "other" if specified name not found platformStyle = PlatformStyle::instantiate("other"); @@ -520,7 +520,7 @@ void BitcoinApplication::initializeResult(bool success) #endif // If -min option passed, start window minimized. - if(GetBoolArg("-min", false)) + if(gArgs.GetBoolArg("-min", false)) { window->showMinimized(); } @@ -575,7 +575,7 @@ int main(int argc, char *argv[]) /// 1. Parse command-line options. These take precedence over anything else. // Command-line options take precedence: - ParseParameters(argc, argv); + gArgs.ParseParameters(argc, argv); // Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory @@ -624,9 +624,9 @@ int main(int argc, char *argv[]) // Show help message immediately after parsing command-line options (for "-lang") and setting locale, // but before showing splash screen. - if (IsArgSet("-?") || IsArgSet("-h") || IsArgSet("-help") || IsArgSet("-version")) + if (gArgs.IsArgSet("-?") || gArgs.IsArgSet("-h") || gArgs.IsArgSet("-help") || gArgs.IsArgSet("-version")) { - HelpMessageDialog help(NULL, IsArgSet("-version") ? HelpMessageDialog::about : HelpMessageDialog::cmdline); + HelpMessageDialog help(NULL, gArgs.IsArgSet("-version") ? HelpMessageDialog::about : HelpMessageDialog::cmdline); help.showOrPrint(); return EXIT_SUCCESS; } @@ -641,11 +641,11 @@ int main(int argc, char *argv[]) if (!fs::is_directory(GetDataDir(false))) { QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), - QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(GetArg("-datadir", "")))); + QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", "")))); return EXIT_FAILURE; } try { - ReadConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)); + gArgs.ReadConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); } catch (const std::exception& e) { QMessageBox::critical(0, QObject::tr(PACKAGE_NAME), QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what())); @@ -709,12 +709,12 @@ int main(int argc, char *argv[]) // Allow parameter interaction before we create the options model app.parameterSetup(); // Load GUI settings from QSettings - app.createOptionsModel(IsArgSet("-resetguisettings")); + app.createOptionsModel(gArgs.IsArgSet("-resetguisettings")); // Subscribe to global signals from core uiInterface.InitMessage.connect(InitMessage); - if (GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !GetBoolArg("-min", false)) + if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false)) app.createSplashScreen(networkStyle.data()); try diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 7ae5bfcd3974..5e5cc6e13dbe 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -434,7 +434,7 @@ void openDebugLogfile() void openConfigfile() { - fs::path pathConfig = GetConfigFile(GetArg("-conf", BITCOIN_CONF_FILENAME)); + fs::path pathConfig = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)); /* Open dash.conf with the associated application */ if (fs::exists(pathConfig)) @@ -673,7 +673,7 @@ bool SetStartOnSystemStartup(bool fAutoStart) // Start client minimized QString strArgs = "-min"; // Set -testnet /-regtest options - strArgs += QString::fromStdString(strprintf(" -testnet=%d -regtest=%d", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false))); + strArgs += QString::fromStdString(strprintf(" -testnet=%d -regtest=%d", gArgs.GetBoolArg("-testnet", false), gArgs.GetBoolArg("-regtest", false))); #ifdef UNICODE boost::scoped_array args(new TCHAR[strArgs.length() + 1]); @@ -782,7 +782,7 @@ bool SetStartOnSystemStartup(bool fAutoStart) optionFile << "Name=Dash Core\n"; else optionFile << strprintf("Name=Dash Core (%s)\n", chain); - optionFile << "Exec=" << pszExePath << strprintf(" -min -testnet=%d -regtest=%d\n", GetBoolArg("-testnet", false), GetBoolArg("-regtest", false)); + optionFile << "Exec=" << pszExePath << strprintf(" -min -testnet=%d -regtest=%d\n", gArgs.GetBoolArg("-testnet", false), gArgs.GetBoolArg("-regtest", false)); optionFile << "Terminal=false\n"; optionFile << "Hidden=false\n"; optionFile.close(); diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index bc8bce7a791c..1c7251f3c747 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -132,7 +132,7 @@ Intro::Intro(QWidget *parent) : ); ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(tr(PACKAGE_NAME))); - uint64_t pruneTarget = std::max(0, GetArg("-prune", 0)); + uint64_t pruneTarget = std::max(0, gArgs.GetArg("-prune", 0)); requiredSpace = BLOCK_CHAIN_SIZE; QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); if (pruneTarget) { @@ -192,7 +192,7 @@ bool Intro::pickDataDirectory() QSettings settings; /* If data directory provided on command line, no need to look at settings or show a picking dialog */ - if(!GetArg("-datadir", "").empty()) + if(!gArgs.GetArg("-datadir", "").empty()) return true; /* 1) Default data directory for operating system */ QString dataDirDefaultCurrent = getDefaultDataDirectory(); @@ -201,7 +201,7 @@ bool Intro::pickDataDirectory() /* 3) Check to see if default datadir is the one we expect */ QString dataDirDefaultSettings = settings.value("strDataDirDefault").toString(); - if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || dataDirDefaultCurrent != dataDirDefaultSettings) + if(!fs::exists(GUIUtil::qstringToBoostPath(dataDir)) || gArgs.GetBoolArg("-choosedatadir", DEFAULT_CHOOSE_DATADIR) || dataDirDefaultCurrent != dataDirDefaultSettings) { /* Let the user choose one */ Intro intro; @@ -234,7 +234,7 @@ bool Intro::pickDataDirectory() * (to be consistent with dashd behavior) */ if(dataDir != dataDirDefaultCurrent) - SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting + gArgs.SoftSetArg("-datadir", GUIUtil::qstringToBoostPath(dataDir).string()); // use OS locale for path setting return true; } diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 2d614f7551b9..1f2b7e10b7b3 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -38,7 +38,7 @@ OptionsModel::OptionsModel(QObject *parent, bool resetSettings) : void OptionsModel::addOverriddenOption(const std::string &option) { - strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(GetArg(option, "")) + " "; + strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(gArgs.GetArg(option, "")) + " "; } // Writes all missing QSettings with their default values @@ -109,31 +109,31 @@ void OptionsModel::Init(bool resetSettings) // // If setting doesn't exist create it with defaults. // - // If SoftSetArg() or SoftSetBoolArg() return false we were overridden + // If gArgs.SoftSetArg() or gArgs.SoftSetBoolArg() return false we were overridden // by command-line and show this in the UI. // Main if (!settings.contains("nDatabaseCache")) settings.setValue("nDatabaseCache", (qint64)nDefaultDbCache); - if (!SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString())) + if (!gArgs.SoftSetArg("-dbcache", settings.value("nDatabaseCache").toString().toStdString())) addOverriddenOption("-dbcache"); if (!settings.contains("nThreadsScriptVerif")) settings.setValue("nThreadsScriptVerif", DEFAULT_SCRIPTCHECK_THREADS); - if (!SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString())) + if (!gArgs.SoftSetArg("-par", settings.value("nThreadsScriptVerif").toString().toStdString())) addOverriddenOption("-par"); // Wallet #ifdef ENABLE_WALLET if (!settings.contains("bSpendZeroConfChange")) settings.setValue("bSpendZeroConfChange", true); - if (!SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool())) + if (!gArgs.SoftSetBoolArg("-spendzeroconfchange", settings.value("bSpendZeroConfChange").toBool())) addOverriddenOption("-spendzeroconfchange"); // PrivateSend if (!settings.contains("nPrivateSendRounds")) settings.setValue("nPrivateSendRounds", DEFAULT_PRIVATESEND_ROUNDS); - if (!SoftSetArg("-privatesendrounds", settings.value("nPrivateSendRounds").toString().toStdString())) + if (!gArgs.SoftSetArg("-privatesendrounds", settings.value("nPrivateSendRounds").toString().toStdString())) addOverriddenOption("-privatesendrounds"); privateSendClient.nPrivateSendRounds = settings.value("nPrivateSendRounds").toInt(); @@ -144,13 +144,13 @@ void OptionsModel::Init(bool resetSettings) else settings.setValue("nPrivateSendAmount", settings.value("nAnonymizeDashAmount").toInt()); } - if (!SoftSetArg("-privatesendamount", settings.value("nPrivateSendAmount").toString().toStdString())) + if (!gArgs.SoftSetArg("-privatesendamount", settings.value("nPrivateSendAmount").toString().toStdString())) addOverriddenOption("-privatesendamount"); privateSendClient.nPrivateSendAmount = settings.value("nPrivateSendAmount").toInt(); if (!settings.contains("fPrivateSendMultiSession")) settings.setValue("fPrivateSendMultiSession", DEFAULT_PRIVATESEND_MULTISESSION); - if (!SoftSetBoolArg("-privatesendmultisession", settings.value("fPrivateSendMultiSession").toBool())) + if (!gArgs.SoftSetBoolArg("-privatesendmultisession", settings.value("fPrivateSendMultiSession").toBool())) addOverriddenOption("-privatesendmultisession"); privateSendClient.fPrivateSendMultiSession = settings.value("fPrivateSendMultiSession").toBool(); #endif @@ -158,12 +158,12 @@ void OptionsModel::Init(bool resetSettings) // Network if (!settings.contains("fUseUPnP")) settings.setValue("fUseUPnP", DEFAULT_UPNP); - if (!SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool())) + if (!gArgs.SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool())) addOverriddenOption("-upnp"); if (!settings.contains("fListen")) settings.setValue("fListen", DEFAULT_LISTEN); - if (!SoftSetBoolArg("-listen", settings.value("fListen").toBool())) + if (!gArgs.SoftSetBoolArg("-listen", settings.value("fListen").toBool())) addOverriddenOption("-listen"); if (!settings.contains("fUseProxy")) @@ -171,9 +171,9 @@ void OptionsModel::Init(bool resetSettings) if (!settings.contains("addrProxy")) settings.setValue("addrProxy", "127.0.0.1:9050"); // Only try to set -proxy, if user has enabled fUseProxy - if (settings.value("fUseProxy").toBool() && !SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString())) + if (settings.value("fUseProxy").toBool() && !gArgs.SoftSetArg("-proxy", settings.value("addrProxy").toString().toStdString())) addOverriddenOption("-proxy"); - else if(!settings.value("fUseProxy").toBool() && !GetArg("-proxy", "").empty()) + else if(!settings.value("fUseProxy").toBool() && !gArgs.GetArg("-proxy", "").empty()) addOverriddenOption("-proxy"); if (!settings.contains("fUseSeparateProxyTor")) @@ -181,15 +181,15 @@ void OptionsModel::Init(bool resetSettings) if (!settings.contains("addrSeparateProxyTor")) settings.setValue("addrSeparateProxyTor", "127.0.0.1:9050"); // Only try to set -onion, if user has enabled fUseSeparateProxyTor - if (settings.value("fUseSeparateProxyTor").toBool() && !SoftSetArg("-onion", settings.value("addrSeparateProxyTor").toString().toStdString())) + if (settings.value("fUseSeparateProxyTor").toBool() && !gArgs.SoftSetArg("-onion", settings.value("addrSeparateProxyTor").toString().toStdString())) addOverriddenOption("-onion"); - else if(!settings.value("fUseSeparateProxyTor").toBool() && !GetArg("-onion", "").empty()) + else if(!settings.value("fUseSeparateProxyTor").toBool() && !gArgs.GetArg("-onion", "").empty()) addOverriddenOption("-onion"); // Display if (!settings.contains("language")) settings.setValue("language", ""); - if (!SoftSetArg("-lang", settings.value("language").toString().toStdString())) + if (!gArgs.SoftSetArg("-lang", settings.value("language").toString().toStdString())) addOverriddenOption("-lang"); language = settings.value("language").toString(); diff --git a/src/qt/paymentrequestplus.cpp b/src/qt/paymentrequestplus.cpp index 523000144551..af3056c3d529 100644 --- a/src/qt/paymentrequestplus.cpp +++ b/src/qt/paymentrequestplus.cpp @@ -145,7 +145,7 @@ bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) c int error = X509_STORE_CTX_get_error(store_ctx); // For testing payment requests, we allow self signed root certs! // This option is just shown in the UI options, if -help-debug is enabled. - if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && GetBoolArg("-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) { + if (!(error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && gArgs.GetBoolArg("-allowselfsignedrootcertificates", DEFAULT_SELFSIGNED_ROOTCERTS))) { throw SSLVerifyError(X509_verify_cert_error_string(error)); } else { qDebug() << "PaymentRequestPlus::getMerchant: Allowing self signed root certificate, because -allowselfsignedrootcertificates is true."; diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index e461da41e6a1..7de53e56fb04 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -123,7 +123,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) // Note: use "-system-" default here so that users can pass -rootcertificates="" // and get 'I don't like X.509 certificates, don't trust anybody' behavior: - QString certFile = QString::fromStdString(GetArg("-rootcertificates", "-system-")); + QString certFile = QString::fromStdString(gArgs.GetArg("-rootcertificates", "-system-")); // Empty store if (certFile.isEmpty()) { diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index d99530d53859..b50f11d90a1b 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -467,7 +467,7 @@ RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) : #ifdef ENABLE_WALLET ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0)); std::string walletPath = GetDataDir().string(); - walletPath += QDir::separator().toLatin1() + GetArg("-wallet", "wallet.dat"); + walletPath += QDir::separator().toLatin1() + gArgs.GetArg("-wallet", "wallet.dat"); ui->wallet_path->setText(QString::fromStdString(walletPath)); #else ui->label_berkeleyDBVersion->hide(); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index 580540a3a576..d90f32483aea 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -52,11 +52,11 @@ SplashScreen::SplashScreen(Qt::WindowFlags f, const NetworkStyle *networkStyle) QString titleAddText = networkStyle->getTitleAddText(); // networkstyle.cpp can't (yet) read themes, so we do it here to get the correct Splash-screen QString splashScreenPath = ":/images/" + GUIUtil::getThemeName() + "/splash"; - if(GetBoolArg("-regtest", false)) + if(gArgs.GetBoolArg("-regtest", false)) splashScreenPath = ":/images/" + GUIUtil::getThemeName() + "/splash_testnet"; - if(GetBoolArg("-testnet", false)) + if(gArgs.GetBoolArg("-testnet", false)) splashScreenPath = ":/images/" + GUIUtil::getThemeName() + "/splash_testnet"; - if(IsArgSet("-devnet")) + if(gArgs.IsArgSet("-devnet")) splashScreenPath = ":/images/" + GUIUtil::getThemeName() + "/splash_testnet"; QString font = QApplication::font().toString(); diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index 239949626d96..ff78b6f04045 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -47,7 +47,7 @@ void RPCNestedTests::rpcNestedTests() std::string path = QDir::tempPath().toStdString() + "/" + strprintf("test_dash_qt_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); QDir dir(QString::fromStdString(path)); dir.mkpath("."); - ForceSetArg("-datadir", path); + gArgs.ForceSetArg("-datadir", path); //mempool.setSanityCheck(1.0); evoDb = new CEvoDB(1 << 20, true, true); pblocktree = new CBlockTreeDB(1 << 20, true); diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index e5bb8869e951..e5e729df54a5 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -80,7 +80,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, HelpMode helpMode) : cursor.insertBlock(); std::string strUsage = HelpMessage(HMM_BITCOIN_QT); - const bool showDebug = GetBoolArg("-help-debug", false); + const bool showDebug = gArgs.GetBoolArg("-help-debug", false); strUsage += HelpMessageGroup(tr("UI Options:").toStdString()); if (showDebug) { strUsage += HelpMessageOpt("-allowselfsignedrootcertificates", strprintf("Allow self signed root certificates (default: %u)", DEFAULT_SELFSIGNED_ROOTCERTS)); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 31875dc6fda6..2a8e8fbf16e8 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -835,7 +835,7 @@ bool WalletModel::abandonTransaction(uint256 hash) const bool WalletModel::isWalletEnabled() { - return !GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET); + return !gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET); } bool WalletModel::hdEnabled() const diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e2cfae447baf..fab1fb2ff277 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1254,8 +1254,8 @@ UniValue gettxout(const JSONRPCRequest& request) UniValue verifychain(const JSONRPCRequest& request) { - int nCheckLevel = GetArg("-checklevel", DEFAULT_CHECKLEVEL); - int nCheckDepth = GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); + int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL); + int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); if (request.fHelp || request.params.size() > 2) throw std::runtime_error( "verifychain ( checklevel nblocks )\n" @@ -1588,7 +1588,7 @@ UniValue mempoolInfoToJSON() ret.push_back(Pair("size", (int64_t) mempool.size())); ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize())); ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage())); - size_t maxmempool = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; + size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; ret.push_back(Pair("maxmempool", (int64_t) maxmempool)); ret.push_back(Pair("mempoolminfee", ValueFromAmount(mempool.GetMinFee(maxmempool).GetFeePerK()))); diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index a20fa89ad08a..cff94103f5c5 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -69,7 +69,7 @@ static const std::string COOKIEAUTH_FILE = ".cookie"; fs::path GetAuthCookieFile() { - fs::path path(GetArg("-rpccookiefile", COOKIEAUTH_FILE)); + fs::path path(gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE)); if (!path.is_complete()) path = GetDataDir() / path; return path; } diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 7033d930f987..eefde0e5e962 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -575,7 +575,7 @@ std::string HelpExampleRpc(const std::string& methodname, const std::string& arg { return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", " "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;'" - " http://127.0.0.1:" + strprintf("%d", GetArg("-rpcport", BaseParams().RPCPort())) + "/\n"; + " http://127.0.0.1:" + strprintf("%d", gArgs.GetArg("-rpcport", BaseParams().RPCPort())) + "/\n"; } void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface) diff --git a/src/script/sigcache.cpp b/src/script/sigcache.cpp index 4303920caff6..d61ac2e0a475 100644 --- a/src/script/sigcache.cpp +++ b/src/script/sigcache.cpp @@ -74,7 +74,7 @@ void InitSignatureCache() { // nMaxCacheSize is unsigned. If -maxsigcachesize is set to zero, // setup_bytes creates the minimum possible cache (2 elements). - size_t nMaxCacheSize = std::min(std::max((int64_t)0, GetArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE)), MAX_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20); + size_t nMaxCacheSize = std::min(std::max((int64_t)0, gArgs.GetArg("-maxsigcachesize", DEFAULT_MAX_SIG_CACHE_SIZE)), MAX_MAX_SIG_CACHE_SIZE) * ((size_t) 1 << 20); size_t nElems = signatureCache.setup_bytes(nMaxCacheSize); LogPrintf("Using %zu MiB out of %zu requested for signature cache, able to store %zu elements\n", (nElems*sizeof(uint256)) >>20, nMaxCacheSize>>20, nElems); diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 275b40356695..cb51f1982f84 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) std::atomic interruptDummy(false); connman->ClearBanned(); - ForceSetArg("-banscore", "111"); // because 11 is my favorite number + gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, "", true); dummyNode1.SetSendVersion(PROTOCOL_VERSION); @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) Misbehaving(dummyNode1.GetId(), 1); SendMessages(&dummyNode1, *connman, interruptDummy); BOOST_CHECK(connman->IsBanned(addr1)); - ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); + gArgs.ForceSetArg("-banscore", std::to_string(DEFAULT_BANSCORE_THRESHOLD)); } BOOST_AUTO_TEST_CASE(DoS_bantime) diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index 99ca271f3241..b9ce280d047b 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -28,135 +28,135 @@ static void ResetArgs(const std::string& strArg) BOOST_FOREACH(std::string& s, vecArg) vecChar.push_back(s.c_str()); - ParseParameters(vecChar.size(), &vecChar[0]); + gArgs.ParseParameters(vecChar.size(), &vecChar[0]); } BOOST_AUTO_TEST_CASE(boolarg) { ResetArgs("-foo"); - BOOST_CHECK(GetBoolArg("-foo", false)); - BOOST_CHECK(GetBoolArg("-foo", true)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", true)); - BOOST_CHECK(!GetBoolArg("-fo", false)); - BOOST_CHECK(GetBoolArg("-fo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-fo", false)); + BOOST_CHECK(gArgs.GetBoolArg("-fo", true)); - BOOST_CHECK(!GetBoolArg("-fooo", false)); - BOOST_CHECK(GetBoolArg("-fooo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-fooo", false)); + BOOST_CHECK(gArgs.GetBoolArg("-fooo", true)); ResetArgs("-foo=0"); - BOOST_CHECK(!GetBoolArg("-foo", false)); - BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); ResetArgs("-foo=1"); - BOOST_CHECK(GetBoolArg("-foo", false)); - BOOST_CHECK(GetBoolArg("-foo", true)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", true)); // New 0.6 feature: auto-map -nosomething to !-something: ResetArgs("-nofoo"); - BOOST_CHECK(!GetBoolArg("-foo", false)); - BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); ResetArgs("-nofoo=1"); - BOOST_CHECK(!GetBoolArg("-foo", false)); - BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); ResetArgs("-foo -nofoo"); // -nofoo should win - BOOST_CHECK(!GetBoolArg("-foo", false)); - BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); ResetArgs("-foo=1 -nofoo=1"); // -nofoo should win - BOOST_CHECK(!GetBoolArg("-foo", false)); - BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); ResetArgs("-foo=0 -nofoo=0"); // -nofoo=0 should win - BOOST_CHECK(GetBoolArg("-foo", false)); - BOOST_CHECK(GetBoolArg("-foo", true)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", true)); // New 0.6 feature: treat -- same as -: ResetArgs("--foo=1"); - BOOST_CHECK(GetBoolArg("-foo", false)); - BOOST_CHECK(GetBoolArg("-foo", true)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", true)); ResetArgs("--nofoo=1"); - BOOST_CHECK(!GetBoolArg("-foo", false)); - BOOST_CHECK(!GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); } BOOST_AUTO_TEST_CASE(stringarg) { ResetArgs(""); - BOOST_CHECK_EQUAL(GetArg("-foo", ""), ""); - BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), "eleven"); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), ""); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "eleven"); ResetArgs("-foo -bar"); - BOOST_CHECK_EQUAL(GetArg("-foo", ""), ""); - BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), ""); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), ""); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), ""); ResetArgs("-foo="); - BOOST_CHECK_EQUAL(GetArg("-foo", ""), ""); - BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), ""); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), ""); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), ""); ResetArgs("-foo=11"); - BOOST_CHECK_EQUAL(GetArg("-foo", ""), "11"); - BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), "11"); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "11"); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "11"); ResetArgs("-foo=eleven"); - BOOST_CHECK_EQUAL(GetArg("-foo", ""), "eleven"); - BOOST_CHECK_EQUAL(GetArg("-foo", "eleven"), "eleven"); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "eleven"); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", "eleven"), "eleven"); } BOOST_AUTO_TEST_CASE(intarg) { ResetArgs(""); - BOOST_CHECK_EQUAL(GetArg("-foo", 11), 11); - BOOST_CHECK_EQUAL(GetArg("-foo", 0), 0); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 11), 11); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 0), 0); ResetArgs("-foo -bar"); - BOOST_CHECK_EQUAL(GetArg("-foo", 11), 0); - BOOST_CHECK_EQUAL(GetArg("-bar", 11), 0); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 11), 0); + BOOST_CHECK_EQUAL(gArgs.GetArg("-bar", 11), 0); ResetArgs("-foo=11 -bar=12"); - BOOST_CHECK_EQUAL(GetArg("-foo", 0), 11); - BOOST_CHECK_EQUAL(GetArg("-bar", 11), 12); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 0), 11); + BOOST_CHECK_EQUAL(gArgs.GetArg("-bar", 11), 12); ResetArgs("-foo=NaN -bar=NotANumber"); - BOOST_CHECK_EQUAL(GetArg("-foo", 1), 0); - BOOST_CHECK_EQUAL(GetArg("-bar", 11), 0); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", 1), 0); + BOOST_CHECK_EQUAL(gArgs.GetArg("-bar", 11), 0); } BOOST_AUTO_TEST_CASE(doubledash) { ResetArgs("--foo"); - BOOST_CHECK_EQUAL(GetBoolArg("-foo", false), true); + BOOST_CHECK_EQUAL(gArgs.GetBoolArg("-foo", false), true); ResetArgs("--foo=verbose --bar=1"); - BOOST_CHECK_EQUAL(GetArg("-foo", ""), "verbose"); - BOOST_CHECK_EQUAL(GetArg("-bar", 0), 1); + BOOST_CHECK_EQUAL(gArgs.GetArg("-foo", ""), "verbose"); + BOOST_CHECK_EQUAL(gArgs.GetArg("-bar", 0), 1); } BOOST_AUTO_TEST_CASE(boolargno) { ResetArgs("-nofoo"); - BOOST_CHECK(!GetBoolArg("-foo", true)); - BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); ResetArgs("-nofoo=1"); - BOOST_CHECK(!GetBoolArg("-foo", true)); - BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); ResetArgs("-nofoo=0"); - BOOST_CHECK(GetBoolArg("-foo", true)); - BOOST_CHECK(GetBoolArg("-foo", false)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", true)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", false)); ResetArgs("-foo --nofoo"); // --nofoo should win - BOOST_CHECK(!GetBoolArg("-foo", true)); - BOOST_CHECK(!GetBoolArg("-foo", false)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", true)); + BOOST_CHECK(!gArgs.GetBoolArg("-foo", false)); ResetArgs("-nofoo -foo"); // foo always wins: - BOOST_CHECK(GetBoolArg("-foo", true)); - BOOST_CHECK(GetBoolArg("-foo", false)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", true)); + BOOST_CHECK(gArgs.GetBoolArg("-foo", false)); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 0053764eb850..876667649a06 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -93,7 +93,7 @@ bool TestSequenceLocks(const CTransaction &tx, int flags) void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, std::vector& txFirst) { // Disable free transactions, otherwise TX selection is non-deterministic - SoftSetArg("-blockprioritysize", "0"); + gArgs.SoftSetArg("-blockprioritysize", "0"); // Test the ancestor feerate transaction selection. TestMemPoolEntryHelper entry; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index ea3ea35a4ac7..157b719e1d93 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(cnode_listen_port) BOOST_CHECK(port == Params().GetDefaultPort()); // test set port unsigned short altPort = 12345; - SoftSetArg("-port", std::to_string(altPort)); + gArgs.SoftSetArg("-port", std::to_string(altPort)); port = GetListenPort(); BOOST_CHECK(port == altPort); } diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 6964fb55337a..6bcb272dbaf1 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(get_next_work) BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, params), 0x1b1441de); // Block #123457 has 0x1b1441de // test special rules for slow blocks on devnet/testnet - SoftSetBoolArg("-devnet", true); + gArgs.SoftSetBoolArg("-devnet", true); SelectParams(CBaseChainParams::DEVNET); const Consensus::Params& paramsdev = Params().GetConsensus(); diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index 0a5cb1a8575f..6a9984ef1c50 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -71,7 +71,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_dash_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); fs::create_directories(pathTemp); - ForceSetArg("-datadir", pathTemp.string()); + gArgs.ForceSetArg("-datadir", pathTemp.string()); mempool.setSanityCheck(1.0); g_connman = std::unique_ptr(new CConnman(0x1337, 0x1337)); // Deterministic randomness for tests. connman = g_connman.get(); diff --git a/src/timedata.cpp b/src/timedata.cpp index dbec1fa76be6..e5cdd5497dd3 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -82,7 +82,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) int64_t nMedian = vTimeOffsets.median(); std::vector vSorted = vTimeOffsets.sorted(); // Only let other nodes change our time by so much - if (abs64(nMedian) <= std::max(0, GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT))) + if (abs64(nMedian) <= std::max(0, gArgs.GetArg("-maxtimeadjustment", DEFAULT_MAX_TIME_ADJUSTMENT))) { nTimeOffset = nMedian; } diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 3c6455f37126..86d839558cb7 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -525,7 +525,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply& // Now that we know Tor is running setup the proxy for onion addresses // if -onion isn't set to something else. - if (GetArg("-onion", "") == "") { + if (gArgs.GetArg("-onion", "") == "") { CService resolved(LookupNumeric("127.0.0.1", 9050)); proxyType addrOnion = proxyType(resolved, true); SetProxy(NET_TOR, addrOnion); @@ -642,7 +642,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro * cookie: hex-encoded ~/.tor/control_auth_cookie * password: "password" */ - std::string torpassword = GetArg("-torpassword", ""); + std::string torpassword = gArgs.GetArg("-torpassword", ""); if (!torpassword.empty()) { if (methods.count("HASHEDPASSWORD")) { LogPrint(BCLog::TOR, "tor: Using HASHEDPASSWORD authentication\n"); @@ -735,7 +735,7 @@ static boost::thread torControlThread; static void TorControlThread() { - TorController ctrl(gBase, GetArg("-torcontrol", DEFAULT_TOR_CONTROL)); + TorController ctrl(gBase, gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL)); event_base_dispatch(gBase); } diff --git a/src/txmempool.cpp b/src/txmempool.cpp index e2b7686ac337..1836b13529e9 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1400,7 +1400,7 @@ double CTxMemPool::UsedMemoryShare() const // this param is calculated in such way in other places (see AppInit // function in src/init.cpp or mempoolInfoToJSON function in // src/rpc/blockchain.cpp) - size_t maxmempool = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; + size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; return double(DynamicMemoryUsage()) / maxmempool; } diff --git a/src/validation.cpp b/src/validation.cpp index e37291b937e6..25b9dec5302e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -653,7 +653,7 @@ void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool f // We also need to remove any now-immature transactions mempool.removeForReorg(pcoinsTip, chainActive.Tip()->nHeight + 1, STANDARD_LOCKTIME_VERIFY_FLAGS); // Re-limit mempool size, in case we added any transactions - LimitMempoolSize(mempool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); + LimitMempoolSize(mempool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); } static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx, bool fLimitFree, @@ -841,7 +841,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false, strprintf("%d", nSigOps)); - CAmount mempoolRejectFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize); + CAmount mempoolRejectFee = pool.GetMinFee(gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize); if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) { return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee)); } @@ -858,10 +858,10 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // Calculate in-mempool ancestors, up to a limit. CTxMemPool::setEntries setAncestors; - size_t nLimitAncestors = GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); - size_t nLimitAncestorSize = GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000; - size_t nLimitDescendants = GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); - size_t nLimitDescendantSize = GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000; + size_t nLimitAncestors = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); + size_t nLimitAncestorSize = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000; + size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); + size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000; std::string errString; if (!pool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) { return state.DoS(0, false, REJECT_NONSTANDARD, "too-long-mempool-chain", false, errString); @@ -921,7 +921,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // trim mempool and check if tx was trimmed if (!fOverrideMempoolLimit) { - LimitMempoolSize(pool, GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); + LimitMempoolSize(pool, gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000, gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60); if (!pool.exists(hash)) return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool full"); } @@ -1258,7 +1258,7 @@ CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL; static void AlertNotify(const std::string& strMessage) { uiInterface.NotifyAlertChanged(); - std::string strCmd = GetArg("-alertnotify", ""); + std::string strCmd = gArgs.GetArg("-alertnotify", ""); if (strCmd.empty()) return; // Alert text should be plain ascii coming from a trusted source, but to @@ -2421,7 +2421,7 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & if (nLastSetChain == 0) { nLastSetChain = nNow; } - int64_t nMempoolSizeMax = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; + int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; int64_t cacheSize = pcoinsTip->DynamicMemoryUsage() * DB_PEAK_USAGE_FACTOR; int64_t nTotalSpace = nCoinCacheUsage + std::max(nMempoolSizeMax - nMempoolUsage, 0); // The cache is large and we're within 10% and 10 MiB of the limit, but we have time now (not in the middle of a block processing). @@ -3012,7 +3012,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return false; } - int nStopAtHeight = GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); + int nStopAtHeight = gArgs.GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); return true; @@ -4257,18 +4257,18 @@ bool InitBlockIndex(const CChainParams& chainparams) return true; // Use the provided setting for -txindex in the new database - fTxIndex = GetBoolArg("-txindex", DEFAULT_TXINDEX); + fTxIndex = gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX); pblocktree->WriteFlag("txindex", fTxIndex); // Use the provided setting for -addressindex in the new database - fAddressIndex = GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX); + fAddressIndex = gArgs.GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX); pblocktree->WriteFlag("addressindex", fAddressIndex); // Use the provided setting for -timestampindex in the new database - fTimestampIndex = GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX); + fTimestampIndex = gArgs.GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX); pblocktree->WriteFlag("timestampindex", fTimestampIndex); - fSpentIndex = GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); + fSpentIndex = gArgs.GetBoolArg("-spentindex", DEFAULT_SPENTINDEX); pblocktree->WriteFlag("spentindex", fSpentIndex); LogPrintf("Initializing databases...\n"); @@ -4633,13 +4633,13 @@ static const uint64_t MEMPOOL_DUMP_VERSION = 1; bool LoadMempool(void) { - if (GetBoolArg("-zapwallettxes", false)) { + if (gArgs.GetBoolArg("-zapwallettxes", false)) { LogPrintf("Skipping mempool.dat because of zapwallettxes\n"); return true; } const CChainParams& chainparams = Params(); - int64_t nExpiryTimeout = GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; + int64_t nExpiryTimeout = gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; FILE* filestr = fsbridge::fopen(GetDataDir() / "mempool.dat", "rb"); CAutoFile file(filestr, SER_DISK, CLIENT_VERSION); if (file.IsNull()) { diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index fea26f3484b5..2d4bd21fabea 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -80,7 +80,7 @@ bool CDBEnv::Open(const fs::path& pathIn) LogPrintf("CDBEnv::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string()); unsigned int nEnvFlags = 0; - if (GetBoolArg("-privdb", DEFAULT_WALLET_PRIVDB)) + if (gArgs.GetBoolArg("-privdb", DEFAULT_WALLET_PRIVDB)) nEnvFlags |= DB_PRIVATE; dbenv->set_lg_dir(pathLogDir.string().c_str()); @@ -430,7 +430,7 @@ void CDB::Flush() if (fReadOnly) nMinutes = 1; - env->dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0); + env->dbenv->txn_checkpoint(nMinutes ? gArgs.GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0); } void CDB::Close() diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 39004fb9c24f..b08a4abc2df8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3050,7 +3050,7 @@ static const CRPCCommand commands[] = void RegisterWalletRPCCommands(CRPCTable &t) { - if (GetBoolArg("-disablewallet", false)) + if (gArgs.GetBoolArg("-disablewallet", false)) return; for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fa8b081f142a..56c311b122f4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -421,7 +421,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl return true; // Verify KeePassIntegration - if (strWalletPassphrase == "keepass" && GetBoolArg("-keepass", false)) { + if (strWalletPassphrase == "keepass" && gArgs.GetBoolArg("-keepass", false)) { try { strWalletPassphraseFinal = keePassInt.retrievePassphrase(); } catch (std::exception& e) { @@ -447,7 +447,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl if(nWalletBackups == -2) { TopUpKeyPool(); LogPrintf("Keypool replenished, re-initializing automatic backups.\n"); - nWalletBackups = GetArg("-createwalletbackups", 10); + nWalletBackups = gArgs.GetArg("-createwalletbackups", 10); } return true; } @@ -464,7 +464,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, SecureString strOldWalletPassphraseFinal; // Verify KeePassIntegration - if(strOldWalletPassphrase == "keepass" && GetBoolArg("-keepass", false)) { + if(strOldWalletPassphrase == "keepass" && gArgs.GetBoolArg("-keepass", false)) { bUseKeePass = true; try { strOldWalletPassphraseFinal = keePassInt.retrievePassphrase(); @@ -604,17 +604,17 @@ void CWallet::Flush(bool shutdown) bool CWallet::Verify() { - if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) + if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; uiInterface.InitMessage(_("Verifying wallet...")); - std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + std::string walletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT); std::string strError; if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) return InitError(strError); - if (GetBoolArg("-salvagewallet", false)) + if (gArgs.GetBoolArg("-salvagewallet", false)) { // Recover readable keypairs: CWallet dummyWallet; @@ -824,7 +824,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) dbw->Rewrite(); // Update KeePass if necessary - if(GetBoolArg("-keepass", false)) { + if(gArgs.GetBoolArg("-keepass", false)) { LogPrintf("CWallet::EncryptWallet -- Updating KeePass with new passphrase"); try { keePassInt.updatePassphrase(strWalletPassphrase); @@ -1086,7 +1086,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose) NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED); // notify an external script when a wallet transaction comes in or is updated - std::string strCmd = GetArg("-walletnotify", ""); + std::string strCmd = gArgs.GetArg("-walletnotify", ""); if ( !strCmd.empty()) { @@ -1555,21 +1555,21 @@ void CWallet::GenerateNewHDChain() { CHDChain newHdChain; - std::string strSeed = GetArg("-hdseed", "not hex"); + std::string strSeed = gArgs.GetArg("-hdseed", "not hex"); - if(IsArgSet("-hdseed") && IsHex(strSeed)) { + if(gArgs.IsArgSet("-hdseed") && IsHex(strSeed)) { std::vector vchSeed = ParseHex(strSeed); if (!newHdChain.SetSeed(SecureVector(vchSeed.begin(), vchSeed.end()), true)) throw std::runtime_error(std::string(__func__) + ": SetSeed failed"); } else { - if (IsArgSet("-hdseed") && !IsHex(strSeed)) + if (gArgs.IsArgSet("-hdseed") && !IsHex(strSeed)) LogPrintf("CWallet::GenerateNewHDChain -- Incorrect seed, generating random one instead\n"); // NOTE: empty mnemonic means "generate a new one for me" - std::string strMnemonic = GetArg("-mnemonic", ""); + std::string strMnemonic = gArgs.GetArg("-mnemonic", ""); // NOTE: default mnemonic passphrase is an empty string - std::string strMnemonicPassphrase = GetArg("-mnemonicpassphrase", ""); + std::string strMnemonicPassphrase = gArgs.GetArg("-mnemonicpassphrase", ""); SecureVector vchMnemonic(strMnemonic.begin(), strMnemonic.end()); SecureVector vchMnemonicPassphrase(strMnemonicPassphrase.begin(), strMnemonicPassphrase.end()); @@ -2917,8 +2917,8 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm ++it; } - size_t nMaxChainLength = std::min(GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT), GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)); - bool fRejectLongChains = GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS); + size_t nMaxChainLength = std::min(gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT), gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT)); + bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS); bool res = nTargetValue <= nValueFromPresetInputs || SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 6, 0, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend) || @@ -3768,15 +3768,15 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT wtxNew.SetTx(MakeTransactionRef(std::move(txNew))); } - if (GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) { + if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) { // Lastly, ensure this tx will pass the mempool's chain limits LockPoints lp; CTxMemPoolEntry entry(wtxNew.tx, 0, 0, 0, false, 0, lp); CTxMemPool::setEntries setAncestors; - size_t nLimitAncestors = GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); - size_t nLimitAncestorSize = GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000; - size_t nLimitDescendants = GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); - size_t nLimitDescendantSize = GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000; + size_t nLimitAncestors = gArgs.GetArg("-limitancestorcount", DEFAULT_ANCESTOR_LIMIT); + size_t nLimitAncestorSize = gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT)*1000; + size_t nLimitDescendants = gArgs.GetArg("-limitdescendantcount", DEFAULT_DESCENDANT_LIMIT); + size_t nLimitDescendantSize = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT)*1000; std::string errString; if (!mempool.CalculateMemPoolAncestors(entry, setAncestors, nLimitAncestors, nLimitAncestorSize, nLimitDescendants, nLimitDescendantSize, errString)) { strFailReason = _("Transaction has too long of a mempool chain"); @@ -4106,7 +4106,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) if (kpSize > 0) nTargetSize = kpSize; else - nTargetSize = std::max(GetArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 0); + nTargetSize = std::max(gArgs.GetArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 0); // count amount of available keys (internal, external) // make sure the keypool of external and internal keys fits the user selected target (-keypool) @@ -4795,7 +4795,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) // needed to restore wallet transaction meta data after -zapwallettxes std::vector vWtx; - if (GetBoolArg("-zapwallettxes", false)) { + if (gArgs.GetBoolArg("-zapwallettxes", false)) { uiInterface.InitMessage(_("Zapping all transactions from wallet...")); std::unique_ptr dbw(new CWalletDBWrapper(&bitdb, walletFile)); @@ -4844,9 +4844,9 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) } } - if (GetBoolArg("-upgradewallet", fFirstRun)) + if (gArgs.GetBoolArg("-upgradewallet", fFirstRun)) { - int nMaxVersion = GetArg("-upgradewallet", 0); + int nMaxVersion = gArgs.GetArg("-upgradewallet", 0); if (nMaxVersion == 0) // the -upgradewallet without argument case { LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST); @@ -4866,8 +4866,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) if (fFirstRun) { // Create new keyUser and set as default key - if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) { - if (GetArg("-mnemonicpassphrase", "").size() > 256) { + if (gArgs.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsHDEnabled()) { + if (gArgs.GetArg("-mnemonicpassphrase", "").size() > 256) { InitError(_("Mnemonic passphrase is too long, must be at most 256 characters")); return NULL; } @@ -4903,8 +4903,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) } } - else if (IsArgSet("-usehd")) { - bool useHD = GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET); + else if (gArgs.IsArgSet("-usehd")) { + bool useHD = gArgs.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET); if (walletInstance->IsHDEnabled() && !useHD) { InitError(strprintf(_("Error loading %s: You can't disable HD on a already existing HD wallet"), walletInstance->GetName())); @@ -4918,7 +4918,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) } // Warn user every time he starts non-encrypted HD wallet - if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsLocked()) { + if (gArgs.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && !walletInstance->IsLocked()) { InitWarning(_("Make sure to encrypt your wallet and delete all non-encrypted backups after you verified that wallet works!")); } @@ -4927,7 +4927,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) RegisterValidationInterface(walletInstance); CBlockIndex *pindexRescan = chainActive.Genesis(); - if (!GetBoolArg("-rescan", false)) + if (!gArgs.GetBoolArg("-rescan", false)) { CWalletDB walletdb(*walletInstance->dbw); CBlockLocator locator; @@ -4960,7 +4960,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) CWalletDB::IncrementUpdateCounter(); // Restore wallet transaction metadata after -zapwallettxes=1 - if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2") + if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.GetArg("-zapwallettxes", "1") != "2") { CWalletDB walletdb(*walletInstance->dbw); @@ -4984,7 +4984,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) } } } - walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); + walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); { LOCK(walletInstance->cs_wallet); @@ -4999,13 +4999,13 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) bool CWallet::InitLoadWallet() { - if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { + if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); return true; } - std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + std::string walletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT); if (boost::filesystem::path(walletFile).filename() != walletFile) { return InitError(_("-wallet parameter must only specify a filename (not a path)")); @@ -5038,57 +5038,57 @@ void CWallet::postInitProcess(CScheduler& scheduler) bool CWallet::ParameterInteraction() { - if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) + if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; - if (GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && SoftSetBoolArg("-walletbroadcast", false)) { + if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY) && gArgs.SoftSetBoolArg("-walletbroadcast", false)) { LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -walletbroadcast=0\n", __func__); } - if (GetBoolArg("-salvagewallet", false) && SoftSetBoolArg("-rescan", true)) { + if (gArgs.GetBoolArg("-salvagewallet", false) && gArgs.SoftSetBoolArg("-rescan", true)) { // Rewrite just private keys: rescan to find transactions LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); } // -zapwallettx implies a rescan - if (GetBoolArg("-zapwallettxes", false) && SoftSetBoolArg("-rescan", true)) { + if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.SoftSetBoolArg("-rescan", true)) { LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); } - if (GetBoolArg("-sysperms", false)) + if (gArgs.GetBoolArg("-sysperms", false)) return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); - if (GetArg("-prune", 0) && GetBoolArg("-rescan", false)) + if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false)) return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.")); if (::minRelayTxFee.GetFeePerK() > HIGH_TX_FEE_PER_KB) InitWarning(AmountHighWarn("-minrelaytxfee") + " " + _("The wallet will avoid paying less than the minimum relay fee.")); - if (IsArgSet("-mintxfee")) + if (gArgs.IsArgSet("-mintxfee")) { CAmount n = 0; - if (!ParseMoney(GetArg("-mintxfee", ""), n) || 0 == n) - return InitError(AmountErrMsg("mintxfee", GetArg("-mintxfee", ""))); + if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) + return InitError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", ""))); if (n > HIGH_TX_FEE_PER_KB) InitWarning(AmountHighWarn("-mintxfee") + " " + _("This is the minimum transaction fee you pay on every transaction.")); CWallet::minTxFee = CFeeRate(n); } - if (IsArgSet("-fallbackfee")) + if (gArgs.IsArgSet("-fallbackfee")) { CAmount nFeePerK = 0; - if (!ParseMoney(GetArg("-fallbackfee", ""), nFeePerK)) - return InitError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), GetArg("-fallbackfee", ""))); + if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) + return InitError(strprintf(_("Invalid amount for -fallbackfee=: '%s'"), gArgs.GetArg("-fallbackfee", ""))); if (nFeePerK > HIGH_TX_FEE_PER_KB) InitWarning(AmountHighWarn("-fallbackfee") + " " + _("This is the transaction fee you may pay when fee estimates are not available.")); CWallet::fallbackFee = CFeeRate(nFeePerK); } - if (IsArgSet("-paytxfee")) + if (gArgs.IsArgSet("-paytxfee")) { CAmount nFeePerK = 0; - if (!ParseMoney(GetArg("-paytxfee", ""), nFeePerK)) - return InitError(AmountErrMsg("paytxfee", GetArg("-paytxfee", ""))); + if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) + return InitError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", ""))); if (nFeePerK > HIGH_TX_FEE_PER_KB) InitWarning(AmountHighWarn("-paytxfee") + " " + _("This is the transaction fee you will pay if you send a transaction.")); @@ -5097,28 +5097,28 @@ bool CWallet::ParameterInteraction() if (payTxFee < ::minRelayTxFee) { return InitError(strprintf(_("Invalid amount for -paytxfee=: '%s' (must be at least %s)"), - GetArg("-paytxfee", ""), ::minRelayTxFee.ToString())); + gArgs.GetArg("-paytxfee", ""), ::minRelayTxFee.ToString())); } } - if (IsArgSet("-maxtxfee")) + if (gArgs.IsArgSet("-maxtxfee")) { CAmount nMaxFee = 0; - if (!ParseMoney(GetArg("-maxtxfee", ""), nMaxFee)) - return InitError(AmountErrMsg("maxtxfee", GetArg("-maxtxfee", ""))); + if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) + return InitError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", ""))); if (nMaxFee > HIGH_MAX_TX_FEE) InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction.")); maxTxFee = nMaxFee; if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee) { return InitError(strprintf(_("Invalid amount for -maxtxfee=: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"), - GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString())); + gArgs.GetArg("-maxtxfee", ""), ::minRelayTxFee.ToString())); } } - nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); - bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); + nTxConfirmTarget = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET); + bSpendZeroConfChange = gArgs.GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE); - if (IsArgSet("-walletbackupsdir")) { - if (!fs::is_directory(GetArg("-walletbackupsdir", ""))) { + if (gArgs.IsArgSet("-walletbackupsdir")) { + if (!fs::is_directory(gArgs.GetArg("-walletbackupsdir", ""))) { LogPrintf("%s: Warning: incorrect parameter -walletbackupsdir, path must exist! Using default path.\n", __func__); InitWarning("Warning: incorrect parameter -walletbackupsdir, path must exist! Using default path.\n"); @@ -5131,16 +5131,16 @@ bool CWallet::ParameterInteraction() bool CWallet::InitAutoBackup() { - if (GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) + if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; std::string strWarning; std::string strError; - nWalletBackups = GetArg("-createwalletbackups", 10); + nWalletBackups = gArgs.GetArg("-createwalletbackups", 10); nWalletBackups = std::max(0, std::min(10, nWalletBackups)); - std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT); + std::string strWalletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT); if(!AutoBackupWallet(NULL, strWalletFile, strWarning, strError)) { if (!strWarning.empty()) @@ -5292,7 +5292,7 @@ void CWallet::NotifyTransactionLock(const CTransaction &tx, const llmq::CInstant NotifyTransactionChanged(this, txHash, CT_UPDATED); NotifyISLockReceived(); // notify an external script - std::string strCmd = GetArg("-instantsendnotify", ""); + std::string strCmd = gArgs.GetArg("-instantsendnotify", ""); if (!strCmd.empty()) { boost::replace_all(strCmd, "%s", txHash.GetHex()); boost::thread t(runCommand, strCmd); // thread runs free diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 45317aff8653..ec6871036470 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -632,7 +632,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) fNoncriticalErrors = true; // ... but do warn the user there is something wrong. if (strType == "tx") // Rescan if there is a bad transaction record: - SoftSetBoolArg("-rescan", true); + gArgs.SoftSetBoolArg("-rescan", true); } } if (!strErr.empty()) @@ -814,7 +814,7 @@ void MaybeCompactWalletDB() if (fOneThread.exchange(true)) { return; } - if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) { + if (!gArgs.GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET)) { return; } diff --git a/src/warnings.cpp b/src/warnings.cpp index 8c58998039df..148f1dd8f72d 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -58,7 +58,7 @@ std::string GetWarnings(const std::string& strFor) strGUI = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications"); } - if (GetBoolArg("-testsafemode", DEFAULT_TESTSAFEMODE)) + if (gArgs.GetBoolArg("-testsafemode", DEFAULT_TESTSAFEMODE)) strStatusBar = strRPC = strGUI = "testsafemode enabled"; // Misc warnings like out of disk space and clock is wrong diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index c5623ed800ae..8ef0213bad24 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -55,10 +55,10 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create() for (std::map::const_iterator i=factories.begin(); i!=factories.end(); ++i) { std::string arg("-zmq" + i->first); - if (IsArgSet(arg)) + if (gArgs.IsArgSet(arg)) { CZMQNotifierFactory factory = i->second; - std::string address = GetArg(arg, ""); + std::string address = gArgs.GetArg(arg, ""); CZMQAbstractNotifier *notifier = factory(); notifier->SetType(i->first); notifier->SetAddress(address); From 5d5171f4786de5a7fc68ba4494129a17d364c6aa Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Thu, 15 Jun 2017 22:45:55 +0200 Subject: [PATCH 295/987] remove unused gArgs wrappers (#10607) --- src/util.cpp | 6 +++--- src/util.h | 56 ---------------------------------------------------- 2 files changed, 3 insertions(+), 59 deletions(-) diff --git a/src/util.cpp b/src/util.cpp index 5e308664751d..fcc1ce9b36da 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -654,8 +654,8 @@ const fs::path &GetDataDir(bool fNetSpecific) if (!path.empty()) return path; - if (IsArgSet("-datadir")) { - path = fs::system_complete(GetArg("-datadir", "")); + if (gArgs.IsArgSet("-datadir")) { + path = fs::system_complete(gArgs.GetArg("-datadir", "")); if (!fs::is_directory(path)) { path = ""; return path; @@ -730,7 +730,7 @@ void ArgsManager::ReadConfigFile(const std::string& confPath) #ifndef WIN32 fs::path GetPidFile() { - fs::path pathPidFile(GetArg("-pid", BITCOIN_PID_FILENAME)); + fs::path pathPidFile(gArgs.GetArg("-pid", BITCOIN_PID_FILENAME)); if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile; return pathPidFile; } diff --git a/src/util.h b/src/util.h index e0299d1b2614..2e4b4a693f8f 100644 --- a/src/util.h +++ b/src/util.h @@ -304,62 +304,6 @@ void ForceRemoveArg(const std::string& strArg); extern ArgsManager gArgs; -// wrappers using the global ArgsManager: -static inline void ParseParameters(int argc, const char*const argv[]) -{ - gArgs.ParseParameters(argc, argv); -} - -static inline void ReadConfigFile(const std::string& confPath) -{ - gArgs.ReadConfigFile(confPath); -} - -static inline bool SoftSetArg(const std::string& strArg, const std::string& strValue) -{ - return gArgs.SoftSetArg(strArg, strValue); -} - -static inline void ForceSetArg(const std::string& strArg, const std::string& strValue) -{ - gArgs.ForceSetArg(strArg, strValue); -} - -static inline bool IsArgSet(const std::string& strArg) -{ - return gArgs.IsArgSet(strArg); -} - -static inline std::string GetArg(const std::string& strArg, const std::string& strDefault) -{ - return gArgs.GetArg(strArg, strDefault); -} - -static inline int64_t GetArg(const std::string& strArg, int64_t nDefault) -{ - return gArgs.GetArg(strArg, nDefault); -} - -static inline bool GetBoolArg(const std::string& strArg, bool fDefault) -{ - return gArgs.GetBoolArg(strArg, fDefault); -} - -static inline bool SoftSetBoolArg(const std::string& strArg, bool fValue) -{ - return gArgs.SoftSetBoolArg(strArg, fValue); -} - -static inline void ForceSetMultiArgs(const std::string& strArg, const std::vector& values) -{ - gArgs.ForceSetMultiArgs(strArg, values); -} - -static inline void ForceRemoveArg(const std::string& strArg) -{ - gArgs.ForceRemoveArg(strArg); -} - /** * Format a string to be used as group of options in help messages * From dd99dd08c66191ec3b72d0089d44cdf92c5723e6 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 24 Jun 2019 12:02:27 -0500 Subject: [PATCH 296/987] add gArgs for a couple things not caught by scripted diff Signed-off-by: Pasta --- src/init.cpp | 4 ++-- src/util.cpp | 4 ++-- src/wallet/wallet.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 73039b1dad72..de344c06bd5c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -983,8 +983,8 @@ void InitParameterInteraction() } if (gArgs.IsArgSet("-hdseed") && IsHex(gArgs.GetArg("-hdseed", "not hex")) && (gArgs.IsArgSet("-mnemonic") || gArgs.IsArgSet("-mnemonicpassphrase"))) { - ForceRemoveArg("-mnemonic"); - ForceRemoveArg("-mnemonicpassphrase"); + gArgs.ForceRemoveArg("-mnemonic"); + gArgs.ForceRemoveArg("-mnemonicpassphrase"); LogPrintf("%s: parameter interaction: can't use -hdseed and -mnemonic/-mnemonicpassphrase together, will prefer -seed\n", __func__); } #endif // ENABLE_WALLET diff --git a/src/util.cpp b/src/util.cpp index fcc1ce9b36da..9ce303b05705 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -673,10 +673,10 @@ const fs::path &GetDataDir(bool fNetSpecific) fs::path GetBackupsDir() { - if (!IsArgSet("-walletbackupsdir")) + if (!gArgs.IsArgSet("-walletbackupsdir")) return GetDataDir() / "backups"; - return fs::absolute(GetArg("-walletbackupsdir", "")); + return fs::absolute(gArgs.GetArg("-walletbackupsdir", "")); } void ClearDatadirCache() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 56c311b122f4..4d4308fe4ff6 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1583,9 +1583,9 @@ void CWallet::GenerateNewHDChain() throw std::runtime_error(std::string(__func__) + ": SetHDChain failed"); // clean up - ForceRemoveArg("-hdseed"); - ForceRemoveArg("-mnemonic"); - ForceRemoveArg("-mnemonicpassphrase"); + gArgs.ForceRemoveArg("-hdseed"); + gArgs.ForceRemoveArg("-mnemonic"); + gArgs.ForceRemoveArg("-mnemonicpassphrase"); } bool CWallet::SetHDChain(const CHDChain& chain, bool memonly) @@ -5122,7 +5122,7 @@ bool CWallet::ParameterInteraction() LogPrintf("%s: Warning: incorrect parameter -walletbackupsdir, path must exist! Using default path.\n", __func__); InitWarning("Warning: incorrect parameter -walletbackupsdir, path must exist! Using default path.\n"); - ForceRemoveArg("-walletbackupsdir"); + gArgs.ForceRemoveArg("-walletbackupsdir"); } } From 5a760dd90e22ece400f3af458871206a3f2f69ff Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 24 Jun 2019 12:07:26 -0500 Subject: [PATCH 297/987] remove duplicate code Signed-off-by: Pasta --- src/wallet/wallet.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4d4308fe4ff6..c107562c6f71 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3691,8 +3691,6 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT currentConfirmationTarget = coinControl->nConfirmTarget; CAmount nFeeNeeded = std::max(nFeePay, GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator)); - if (coinControl && coinControl->fOverrideFeeRate) - nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes); if(fUseInstantSend) { nFeeNeeded = std::max(nFeeNeeded, CTxLockRequest(txNew).GetMinFee(true)); } From a740a0cecd00056f4c25ba8c2926138eeb60fd1e Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 24 Jun 2019 17:41:02 -0500 Subject: [PATCH 298/987] remove extra argument from code review Signed-off-by: Pasta --- src/validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index 25b9dec5302e..effaff2d7b0d 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -633,7 +633,7 @@ void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool f while (it != disconnectpool.queuedTx.get().rend()) { // ignore validation errors in resurrected transactions CValidationState stateDummy; - if (!fAddToMempool || (*it)->IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, *it, false, NULL, NULL, true)) { + if (!fAddToMempool || (*it)->IsCoinBase() || !AcceptToMemoryPool(mempool, stateDummy, *it, false, NULL, true)) { // If the transaction doesn't make it in to the mempool, remove any // transactions that depend on it (which would now be orphans). mempool.removeRecursive(**it, MemPoolRemovalReason::REORG); From 60475f127218596c7fa26551e84e7f8d10626f0d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 12 Dec 2017 10:27:45 +0100 Subject: [PATCH 299/987] Merge #11831: Always return true if AppInitMain got to the end 07c4838 Always return true if AppInitMain got to the end (Matt Corallo) Pull request description: This should fix a rare zapwallettxes failure on travis, but also avoids having init operations (re-adding wallet transactions to mempool) running after RPC is free'd. I believe this was the failure at https://travis-ci.org/bitcoin/bitcoin/jobs/311747844 (from #11605). Tree-SHA512: f0fea8c1b9265e2eeda57043d541380a3e58e4d9388fa24628a52fd56324257fcd7df0ca02e8f77f66fadd68d951893bab0f610ed9fd0a89b2ccd6bad1efa351 --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index de344c06bd5c..ce49fdd6f3cc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -2158,5 +2158,5 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) pwalletMain->postInitProcess(scheduler); #endif - return !fRequestShutdown; + return true; } From a8c20208195e4c95f65bc09c3ea7510a0d14225a Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 25 Jun 2019 14:38:38 -0500 Subject: [PATCH 300/987] remove unused import cont. Signed-off-by: Pasta --- test/functional/net.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/functional/net.py b/test/functional/net.py index 16476f7d341c..7d87525b05f0 100755 --- a/test/functional/net.py +++ b/test/functional/net.py @@ -14,8 +14,7 @@ assert_equal, assert_raises_jsonrpc, connect_nodes_bi, - p2p_port, - start_nodes, + p2p_port ) From b9a738528cf8785c6fca041ffd57faee736277ed Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 26 Jun 2019 14:39:36 +0300 Subject: [PATCH 301/987] Remove skipped denom from the list on tx commit (#2997) * Remove skipped denom from the list on tx commit Regardless of the tx type (PS or not). * Update src/privatesend/privatesend-client.cpp Co-Authored-By: Alexander Block --- src/privatesend/privatesend-client.cpp | 5 +++++ src/privatesend/privatesend-client.h | 2 +- src/wallet/wallet.cpp | 3 +-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index 01a665b027f7..1ed0fd13290b 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -683,6 +683,11 @@ void CPrivateSendClientManager::AddSkippedDenom(const CAmount& nDenomValue) vecDenominationsSkipped.push_back(nDenomValue); } +void CPrivateSendClientManager::RemoveSkippedDenom(const CAmount& nDenomValue) +{ + vecDenominationsSkipped.erase(std::remove(vecDenominationsSkipped.begin(), vecDenominationsSkipped.end(), nDenomValue), vecDenominationsSkipped.end()); +} + bool CPrivateSendClientManager::WaitForAnotherBlock() { if (!masternodeSync.IsBlockchainSynced()) return true; diff --git a/src/privatesend/privatesend-client.h b/src/privatesend/privatesend-client.h index c156c9917ad1..73f66cf79fd5 100644 --- a/src/privatesend/privatesend-client.h +++ b/src/privatesend/privatesend-client.h @@ -227,7 +227,7 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager bool IsDenomSkipped(const CAmount& nDenomValue); void AddSkippedDenom(const CAmount& nDenomValue); - void ClearSkippedDenominations() { vecDenominationsSkipped.clear(); } + void RemoveSkippedDenom(const CAmount& nDenomValue); void SetMinBlocksToWait(int nMinBlocksToWaitIn) { nMinBlocksToWait = nMinBlocksToWaitIn; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index c107562c6f71..70e92f9d64ab 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3532,8 +3532,6 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (nCoinType == ONLY_DENOMINATED) { nFeeRet += nChange; wtxNew.mapValue["DS"] = "1"; - // recheck skipped denominations during next mixing - privateSendClient.ClearSkippedDenominations(); } else { // Fill a vout to ourself @@ -3811,6 +3809,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon coin.BindWallet(this); NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED); updated_hahes.insert(txin.prevout.hash); + privateSendClient.RemoveSkippedDenom(coin.tx->vout[txin.prevout.n].nValue); } } From b6b486c274356e775f7f4a61c4d4c68435364546 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 15 May 2017 22:49:25 +0200 Subject: [PATCH 302/987] Merge #10376: [tests] fix disconnect_ban intermittency 3ba2c08 [tests] fix disconnect_ban intermittency (John Newbery) Tree-SHA512: f4e1a88b4126ad5e1aa861a99f9b2589194a25610b5e18bcc196e7dccfa02491f0b9549fbb9f9a73776ed5ee2f6b8ade264b92ac378a25c1a92df4b0272487a7 --- test/functional/disconnect_ban.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py index 799bc50594fb..2a9244e9e383 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/disconnect_ban.py @@ -3,6 +3,7 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test node disconnect and ban behavior""" +import time from test_framework.mininode import wait_until from test_framework.test_framework import BitcoinTestFramework @@ -59,13 +60,18 @@ def run_test(self): self.log.info("setban: test persistence across node restart") self.nodes[1].setban("127.0.0.0/32", "add") self.nodes[1].setban("127.0.0.0/24", "add") + # Set the mocktime so we can control when bans expire + old_time = int(time.time()) + self.nodes[1].setmocktime(old_time) self.nodes[1].setban("192.168.0.1", "add", 1) # ban for 1 seconds self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) # ban for 1000 seconds listBeforeShutdown = self.nodes[1].listbanned() assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) set_mocktime(get_mocktime() + 2) set_node_times(self.nodes, get_mocktime()) - assert wait_until(lambda: len(self.nodes[1].listbanned()) == 3, timeout=10) + # Move time forward by 3 seconds so the third ban has expired + self.nodes[1].setmocktime(old_time + 3) + assert_equal(len(self.nodes[1].listbanned()), 3) stop_node(self.nodes[1], 1) From c7aa3723c799a805dee39c56a33eed3e48b589cd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 2 Jun 2017 10:58:27 +0200 Subject: [PATCH 303/987] Merge #10323: Update to latest libsecp256k1 master e7c1b44 Squashed 'src/secp256k1/' changes from 8225239..84973d3 (Pieter Wuille) Tree-SHA512: 3e1ba6e6ad9d68170a1a60bd963f2dbaa8b0ae592cc562e6cd23b2c7653f0b8016e4c682681ae2fb3714106a41f8b89708e16e8f52a42ff3db59fc28262eea0b --- src/secp256k1/Makefile.am | 10 +- src/secp256k1/configure.ac | 17 +- src/secp256k1/include/secp256k1.h | 39 +++- src/secp256k1/src/bench.h | 2 +- src/secp256k1/src/bench_schnorr_verify.c | 73 -------- src/secp256k1/src/ecdsa_impl.h | 16 +- src/secp256k1/src/field_10x26_impl.h | 69 ++++--- src/secp256k1/src/field_5x52_impl.h | 91 +++++++--- src/secp256k1/src/group_impl.h | 6 - src/secp256k1/src/modules/ecdh/main_impl.h | 2 +- src/secp256k1/src/modules/ecdh/tests_impl.h | 30 +++ .../src/modules/recovery/main_impl.h | 2 +- .../src/modules/recovery/tests_impl.h | 143 +++++++++++++++ src/secp256k1/src/scalar_impl.h | 171 +++++++----------- src/secp256k1/src/secp256k1.c | 31 +++- src/secp256k1/src/tests.c | 51 ++++-- src/secp256k1/src/tests_exhaustive.c | 143 ++++++++++++++- src/secp256k1/src/util.h | 5 +- 18 files changed, 623 insertions(+), 278 deletions(-) delete mode 100644 src/secp256k1/src/bench_schnorr_verify.c mode change 100755 => 100644 src/secp256k1/src/secp256k1.c diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am index e5657f7f3130..c071fbe2753c 100644 --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -93,7 +93,10 @@ TESTS = if USE_TESTS noinst_PROGRAMS += tests tests_SOURCES = src/tests.c -tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) +tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) +if !ENABLE_COVERAGE +tests_CPPFLAGS += -DVERIFY +endif tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) tests_LDFLAGS = -static TESTS += tests @@ -102,7 +105,10 @@ endif if USE_EXHAUSTIVE_TESTS noinst_PROGRAMS += exhaustive_tests exhaustive_tests_SOURCES = src/tests_exhaustive.c -exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src $(SECP_INCLUDES) +exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) +if !ENABLE_COVERAGE +exhaustive_tests_CPPFLAGS += -DVERIFY +endif exhaustive_tests_LDADD = $(SECP_LIBS) exhaustive_tests_LDFLAGS = -static TESTS += exhaustive_tests diff --git a/src/secp256k1/configure.ac b/src/secp256k1/configure.ac index ec50ffe3a251..e5fcbcb4edf2 100644 --- a/src/secp256k1/configure.ac +++ b/src/secp256k1/configure.ac @@ -20,7 +20,7 @@ AC_PATH_TOOL(STRIP, strip) AX_PROG_CC_FOR_BUILD if test "x$CFLAGS" = "x"; then - CFLAGS="-O3 -g" + CFLAGS="-g" fi AM_PROG_CC_C_O @@ -89,6 +89,11 @@ AC_ARG_ENABLE(benchmark, [use_benchmark=$enableval], [use_benchmark=no]) +AC_ARG_ENABLE(coverage, + AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]), + [enable_coverage=$enableval], + [enable_coverage=no]) + AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), [use_tests=$enableval], @@ -154,6 +159,14 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], [ AC_MSG_RESULT([no]) ]) +if test x"$enable_coverage" = x"yes"; then + AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) + CFLAGS="$CFLAGS -O0 --coverage" + LDFLAGS="--coverage" +else + CFLAGS="$CFLAGS -O3" +fi + if test x"$use_ecmult_static_precomputation" != x"no"; then save_cross_compiling=$cross_compiling cross_compiling=no @@ -434,6 +447,7 @@ AC_MSG_NOTICE([Using field implementation: $set_field]) AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) +AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage]) AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) AC_MSG_NOTICE([Using jni: $use_jni]) @@ -460,6 +474,7 @@ AC_SUBST(SECP_INCLUDES) AC_SUBST(SECP_LIBS) AC_SUBST(SECP_TEST_LIBS) AC_SUBST(SECP_TEST_INCLUDES) +AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"]) AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) diff --git a/src/secp256k1/include/secp256k1.h b/src/secp256k1/include/secp256k1.h index f268e309d0bf..fc4c5cefbb3b 100644 --- a/src/secp256k1/include/secp256k1.h +++ b/src/secp256k1/include/secp256k1.h @@ -163,6 +163,8 @@ typedef int (*secp256k1_nonce_function)( * * Returns: a newly created context object. * In: flags: which parts of the context to initialize. + * + * See also secp256k1_context_randomize. */ SECP256K1_API secp256k1_context* secp256k1_context_create( unsigned int flags @@ -485,6 +487,28 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( const unsigned char *seckey ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); +/** Negates a private key in place. + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_negate( + const secp256k1_context* ctx, + unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Negates a public key in place. + * + * Returns: 1 always + * Args: ctx: pointer to a context object + * In/Out: pubkey: pointer to the public key to be negated (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_negate( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + /** Tweak a private key by adding tweak to it. * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for * uniformly random 32-byte arrays, or if the resulting private key @@ -543,11 +567,24 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( const unsigned char *tweak ) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); -/** Updates the context randomization. +/** Updates the context randomization to protect against side-channel leakage. * Returns: 1: randomization successfully updated * 0: error * Args: ctx: pointer to a context object (cannot be NULL) * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) + * + * While secp256k1 code is written to be constant-time no matter what secret + * values are, it's possible that a future compiler may output code which isn't, + * and also that the CPU may not emit the same radio frequencies or draw the same + * amount power for all values. + * + * This function provides a seed which is combined into the blinding value: that + * blinding value is added before each multiplication (and removed afterwards) so + * that it does not affect function results, but shields against attacks which + * rely on any input-dependent behaviour. + * + * You should call this after secp256k1_context_create or + * secp256k1_context_clone, and may call this repeatedly afterwards. */ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( secp256k1_context* ctx, diff --git a/src/secp256k1/src/bench.h b/src/secp256k1/src/bench.h index 3a71b4aafa04..d67f08a4267b 100644 --- a/src/secp256k1/src/bench.h +++ b/src/secp256k1/src/bench.h @@ -23,7 +23,7 @@ void print_number(double x) { if (y < 0.0) { y = -y; } - while (y < 100.0) { + while (y > 0 && y < 100.0) { y *= 10.0; c++; } diff --git a/src/secp256k1/src/bench_schnorr_verify.c b/src/secp256k1/src/bench_schnorr_verify.c deleted file mode 100644 index 5f137dda23ef..000000000000 --- a/src/secp256k1/src/bench_schnorr_verify.c +++ /dev/null @@ -1,73 +0,0 @@ -/********************************************************************** - * Copyright (c) 2014 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ - -#include -#include - -#include "include/secp256k1.h" -#include "include/secp256k1_schnorr.h" -#include "util.h" -#include "bench.h" - -typedef struct { - unsigned char key[32]; - unsigned char sig[64]; - unsigned char pubkey[33]; - size_t pubkeylen; -} benchmark_schnorr_sig_t; - -typedef struct { - secp256k1_context *ctx; - unsigned char msg[32]; - benchmark_schnorr_sig_t sigs[64]; - int numsigs; -} benchmark_schnorr_verify_t; - -static void benchmark_schnorr_init(void* arg) { - int i, k; - benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; - - for (i = 0; i < 32; i++) { - data->msg[i] = 1 + i; - } - for (k = 0; k < data->numsigs; k++) { - secp256k1_pubkey pubkey; - for (i = 0; i < 32; i++) { - data->sigs[k].key[i] = 33 + i + k; - } - secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL); - data->sigs[k].pubkeylen = 33; - CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key)); - CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); - } -} - -static void benchmark_schnorr_verify(void* arg) { - int i; - benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; - - for (i = 0; i < 20000 / data->numsigs; i++) { - secp256k1_pubkey pubkey; - data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); - CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen)); - CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0)); - data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); - } -} - - - -int main(void) { - benchmark_schnorr_verify_t data; - - data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - - data.numsigs = 1; - run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000); - - secp256k1_context_destroy(data.ctx); - return 0; -} diff --git a/src/secp256k1/src/ecdsa_impl.h b/src/secp256k1/src/ecdsa_impl.h index 9a42e519bd58..453bb1188066 100644 --- a/src/secp256k1/src/ecdsa_impl.h +++ b/src/secp256k1/src/ecdsa_impl.h @@ -225,14 +225,12 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const #if defined(EXHAUSTIVE_TEST_ORDER) { secp256k1_scalar computed_r; - int overflow = 0; secp256k1_ge pr_ge; secp256k1_ge_set_gej(&pr_ge, &pr); secp256k1_fe_normalize(&pr_ge.x); secp256k1_fe_get_b32(c, &pr_ge.x); - secp256k1_scalar_set_b32(&computed_r, c, &overflow); - /* we fully expect overflow */ + secp256k1_scalar_set_b32(&computed_r, c, NULL); return secp256k1_scalar_eq(sigr, &computed_r); } #else @@ -285,14 +283,10 @@ static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, sec secp256k1_fe_normalize(&r.y); secp256k1_fe_get_b32(b, &r.x); secp256k1_scalar_set_b32(sigr, b, &overflow); - if (secp256k1_scalar_is_zero(sigr)) { - /* P.x = order is on the curve, so technically sig->r could end up zero, which would be an invalid signature. - * This branch is cryptographically unreachable as hitting it requires finding the discrete log of P.x = N. - */ - secp256k1_gej_clear(&rp); - secp256k1_ge_clear(&r); - return 0; - } + /* These two conditions should be checked before calling */ + VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr)); + VERIFY_CHECK(overflow == 0); + if (recid) { /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. diff --git a/src/secp256k1/src/field_10x26_impl.h b/src/secp256k1/src/field_10x26_impl.h index 7b8c07960847..234c13a64423 100644 --- a/src/secp256k1/src/field_10x26_impl.h +++ b/src/secp256k1/src/field_10x26_impl.h @@ -38,10 +38,6 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } VERIFY_CHECK(r == 1); } -#else -static void secp256k1_fe_verify(const secp256k1_fe *a) { - (void)a; -} #endif static void secp256k1_fe_normalize(secp256k1_fe *r) { @@ -325,17 +321,17 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { } static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; - } - } + r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24); + r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22); + r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20); + r->n[3] = (uint32_t)((a[22] >> 6) & 0x3) | ((uint32_t)a[21] << 2) | ((uint32_t)a[20] << 10) | ((uint32_t)a[19] << 18); + r->n[4] = (uint32_t)a[18] | ((uint32_t)a[17] << 8) | ((uint32_t)a[16] << 16) | ((uint32_t)(a[15] & 0x3) << 24); + r->n[5] = (uint32_t)((a[15] >> 2) & 0x3f) | ((uint32_t)a[14] << 6) | ((uint32_t)a[13] << 14) | ((uint32_t)(a[12] & 0xf) << 22); + r->n[6] = (uint32_t)((a[12] >> 4) & 0xf) | ((uint32_t)a[11] << 4) | ((uint32_t)a[10] << 12) | ((uint32_t)(a[9] & 0x3f) << 20); + r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18); + r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24); + r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14); + if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { return 0; } @@ -349,21 +345,42 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<4; j++) { - int limb = (8*i+2*j)/26; - int shift = (8*i+2*j)%26; - c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); - } - r[31-i] = c; - } + r[0] = (a->n[9] >> 14) & 0xff; + r[1] = (a->n[9] >> 6) & 0xff; + r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3); + r[3] = (a->n[8] >> 16) & 0xff; + r[4] = (a->n[8] >> 8) & 0xff; + r[5] = a->n[8] & 0xff; + r[6] = (a->n[7] >> 18) & 0xff; + r[7] = (a->n[7] >> 10) & 0xff; + r[8] = (a->n[7] >> 2) & 0xff; + r[9] = ((a->n[7] & 0x3) << 6) | ((a->n[6] >> 20) & 0x3f); + r[10] = (a->n[6] >> 12) & 0xff; + r[11] = (a->n[6] >> 4) & 0xff; + r[12] = ((a->n[6] & 0xf) << 4) | ((a->n[5] >> 22) & 0xf); + r[13] = (a->n[5] >> 14) & 0xff; + r[14] = (a->n[5] >> 6) & 0xff; + r[15] = ((a->n[5] & 0x3f) << 2) | ((a->n[4] >> 24) & 0x3); + r[16] = (a->n[4] >> 16) & 0xff; + r[17] = (a->n[4] >> 8) & 0xff; + r[18] = a->n[4] & 0xff; + r[19] = (a->n[3] >> 18) & 0xff; + r[20] = (a->n[3] >> 10) & 0xff; + r[21] = (a->n[3] >> 2) & 0xff; + r[22] = ((a->n[3] & 0x3) << 6) | ((a->n[2] >> 20) & 0x3f); + r[23] = (a->n[2] >> 12) & 0xff; + r[24] = (a->n[2] >> 4) & 0xff; + r[25] = ((a->n[2] & 0xf) << 4) | ((a->n[1] >> 22) & 0xf); + r[26] = (a->n[1] >> 14) & 0xff; + r[27] = (a->n[1] >> 6) & 0xff; + r[28] = ((a->n[1] & 0x3f) << 2) | ((a->n[0] >> 24) & 0x3); + r[29] = (a->n[0] >> 16) & 0xff; + r[30] = (a->n[0] >> 8) & 0xff; + r[31] = a->n[0] & 0xff; } SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { diff --git a/src/secp256k1/src/field_5x52_impl.h b/src/secp256k1/src/field_5x52_impl.h index 7a99eb21eccc..8e8b286baff8 100644 --- a/src/secp256k1/src/field_5x52_impl.h +++ b/src/secp256k1/src/field_5x52_impl.h @@ -49,10 +49,6 @@ static void secp256k1_fe_verify(const secp256k1_fe *a) { } VERIFY_CHECK(r == 1); } -#else -static void secp256k1_fe_verify(const secp256k1_fe *a) { - (void)a; -} #endif static void secp256k1_fe_normalize(secp256k1_fe *r) { @@ -288,16 +284,40 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { } static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int i; - r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; - for (i=0; i<32; i++) { - int j; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; - } - } + r->n[0] = (uint64_t)a[31] + | ((uint64_t)a[30] << 8) + | ((uint64_t)a[29] << 16) + | ((uint64_t)a[28] << 24) + | ((uint64_t)a[27] << 32) + | ((uint64_t)a[26] << 40) + | ((uint64_t)(a[25] & 0xF) << 48); + r->n[1] = (uint64_t)((a[25] >> 4) & 0xF) + | ((uint64_t)a[24] << 4) + | ((uint64_t)a[23] << 12) + | ((uint64_t)a[22] << 20) + | ((uint64_t)a[21] << 28) + | ((uint64_t)a[20] << 36) + | ((uint64_t)a[19] << 44); + r->n[2] = (uint64_t)a[18] + | ((uint64_t)a[17] << 8) + | ((uint64_t)a[16] << 16) + | ((uint64_t)a[15] << 24) + | ((uint64_t)a[14] << 32) + | ((uint64_t)a[13] << 40) + | ((uint64_t)(a[12] & 0xF) << 48); + r->n[3] = (uint64_t)((a[12] >> 4) & 0xF) + | ((uint64_t)a[11] << 4) + | ((uint64_t)a[10] << 12) + | ((uint64_t)a[9] << 20) + | ((uint64_t)a[8] << 28) + | ((uint64_t)a[7] << 36) + | ((uint64_t)a[6] << 44); + r->n[4] = (uint64_t)a[5] + | ((uint64_t)a[4] << 8) + | ((uint64_t)a[3] << 16) + | ((uint64_t)a[2] << 24) + | ((uint64_t)a[1] << 32) + | ((uint64_t)a[0] << 40); if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { return 0; } @@ -311,21 +331,42 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { - int i; #ifdef VERIFY VERIFY_CHECK(a->normalized); secp256k1_fe_verify(a); #endif - for (i=0; i<32; i++) { - int j; - int c = 0; - for (j=0; j<2; j++) { - int limb = (8*i+4*j)/52; - int shift = (8*i+4*j)%52; - c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); - } - r[31-i] = c; - } + r[0] = (a->n[4] >> 40) & 0xFF; + r[1] = (a->n[4] >> 32) & 0xFF; + r[2] = (a->n[4] >> 24) & 0xFF; + r[3] = (a->n[4] >> 16) & 0xFF; + r[4] = (a->n[4] >> 8) & 0xFF; + r[5] = a->n[4] & 0xFF; + r[6] = (a->n[3] >> 44) & 0xFF; + r[7] = (a->n[3] >> 36) & 0xFF; + r[8] = (a->n[3] >> 28) & 0xFF; + r[9] = (a->n[3] >> 20) & 0xFF; + r[10] = (a->n[3] >> 12) & 0xFF; + r[11] = (a->n[3] >> 4) & 0xFF; + r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4); + r[13] = (a->n[2] >> 40) & 0xFF; + r[14] = (a->n[2] >> 32) & 0xFF; + r[15] = (a->n[2] >> 24) & 0xFF; + r[16] = (a->n[2] >> 16) & 0xFF; + r[17] = (a->n[2] >> 8) & 0xFF; + r[18] = a->n[2] & 0xFF; + r[19] = (a->n[1] >> 44) & 0xFF; + r[20] = (a->n[1] >> 36) & 0xFF; + r[21] = (a->n[1] >> 28) & 0xFF; + r[22] = (a->n[1] >> 20) & 0xFF; + r[23] = (a->n[1] >> 12) & 0xFF; + r[24] = (a->n[1] >> 4) & 0xFF; + r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4); + r[26] = (a->n[0] >> 40) & 0xFF; + r[27] = (a->n[0] >> 32) & 0xFF; + r[28] = (a->n[0] >> 24) & 0xFF; + r[29] = (a->n[0] >> 16) & 0xFF; + r[30] = (a->n[0] >> 8) & 0xFF; + r[31] = a->n[0] & 0xFF; } SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { diff --git a/src/secp256k1/src/group_impl.h b/src/secp256k1/src/group_impl.h index 2e192b62fd2c..7d723532ff3e 100644 --- a/src/secp256k1/src/group_impl.h +++ b/src/secp256k1/src/group_impl.h @@ -200,12 +200,6 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r) { secp256k1_fe_clear(&r->z); } -static void secp256k1_ge_set_infinity(secp256k1_ge *r) { - r->infinity = 1; - secp256k1_fe_clear(&r->x); - secp256k1_fe_clear(&r->y); -} - static void secp256k1_gej_clear(secp256k1_gej *r) { r->infinity = 0; secp256k1_fe_clear(&r->x); diff --git a/src/secp256k1/src/modules/ecdh/main_impl.h b/src/secp256k1/src/modules/ecdh/main_impl.h index c23e4f82f7fe..9e30fb73dd7f 100644 --- a/src/secp256k1/src/modules/ecdh/main_impl.h +++ b/src/secp256k1/src/modules/ecdh/main_impl.h @@ -16,10 +16,10 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const se secp256k1_gej res; secp256k1_ge pt; secp256k1_scalar s; + VERIFY_CHECK(ctx != NULL); ARG_CHECK(result != NULL); ARG_CHECK(point != NULL); ARG_CHECK(scalar != NULL); - (void)ctx; secp256k1_pubkey_load(ctx, &pt, point); secp256k1_scalar_set_b32(&s, scalar, &overflow); diff --git a/src/secp256k1/src/modules/ecdh/tests_impl.h b/src/secp256k1/src/modules/ecdh/tests_impl.h index 7badc9033f7e..85a5d0a9a69e 100644 --- a/src/secp256k1/src/modules/ecdh/tests_impl.h +++ b/src/secp256k1/src/modules/ecdh/tests_impl.h @@ -7,6 +7,35 @@ #ifndef _SECP256K1_MODULE_ECDH_TESTS_ #define _SECP256K1_MODULE_ECDH_TESTS_ +void test_ecdh_api(void) { + /* Setup context that just counts errors */ + secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_pubkey point; + unsigned char res[32]; + unsigned char s_one[32] = { 0 }; + int32_t ecount = 0; + s_one[31] = 1; + + secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); + CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1); + + /* Check all NULLs are detected */ + CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); + CHECK(ecount == 0); + CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdh(tctx, res, NULL, s_one) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdh(tctx, res, &point, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); + CHECK(ecount == 3); + + /* Cleanup */ + secp256k1_context_destroy(tctx); +} + void test_ecdh_generator_basepoint(void) { unsigned char s_one[32] = { 0 }; secp256k1_pubkey point[2]; @@ -68,6 +97,7 @@ void test_bad_scalar(void) { } void run_ecdh_tests(void) { + test_ecdh_api(); test_ecdh_generator_basepoint(); test_bad_scalar(); } diff --git a/src/secp256k1/src/modules/recovery/main_impl.h b/src/secp256k1/src/modules/recovery/main_impl.h index 86f2f0cb2b53..c6fbe239813a 100755 --- a/src/secp256k1/src/modules/recovery/main_impl.h +++ b/src/secp256k1/src/modules/recovery/main_impl.h @@ -179,7 +179,7 @@ int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubk ARG_CHECK(pubkey != NULL); secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); - ARG_CHECK(recid >= 0 && recid < 4); + VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ secp256k1_scalar_set_b32(&m, msg32, NULL); if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { secp256k1_pubkey_save(pubkey, &q); diff --git a/src/secp256k1/src/modules/recovery/tests_impl.h b/src/secp256k1/src/modules/recovery/tests_impl.h index 8932d5f0afc3..765c7dd81e95 100644 --- a/src/secp256k1/src/modules/recovery/tests_impl.h +++ b/src/secp256k1/src/modules/recovery/tests_impl.h @@ -7,6 +7,146 @@ #ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ #define _SECP256K1_MODULE_RECOVERY_TESTS_ +static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + (void) msg32; + (void) key32; + (void) algo16; + (void) data; + + /* On the first run, return 0 to force a second run */ + if (counter == 0) { + memset(nonce32, 0, 32); + return 1; + } + /* On the second run, return an overflow to force a third run */ + if (counter == 1) { + memset(nonce32, 0xff, 32); + return 1; + } + /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ + memset(nonce32, 1, 32); + return secp256k1_rand_bits(1); +} + +void test_ecdsa_recovery_api(void) { + /* Setup contexts that just count errors */ + secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + secp256k1_pubkey pubkey; + secp256k1_pubkey recpubkey; + secp256k1_ecdsa_signature normal_sig; + secp256k1_ecdsa_recoverable_signature recsig; + unsigned char privkey[32] = { 1 }; + unsigned char message[32] = { 2 }; + int32_t ecount = 0; + int recid = 0; + unsigned char sig[74]; + unsigned char zero_privkey[32] = { 0 }; + unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Check bad contexts and NULLs for signing */ + ecount = 0; + CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0); + CHECK(ecount == 5); + /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ + secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL); + CHECK(ecount == 5); + /* These will all fail, but not in ARG_CHECK way */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); + /* This one will succeed. */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 5); + + /* Check signing with a goofy nonce function */ + + /* Check bad contexts and NULLs for recovery */ + ecount = 0; + CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); + CHECK(ecount == 5); + + /* Check NULLs for conversion */ + CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); + + /* Check NULLs for de/serialization */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); + + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); + CHECK(ecount == 5); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); + CHECK(ecount == 6); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0); + CHECK(ecount == 7); + /* overflow in signature will fail but not affect ecount */ + memcpy(sig, over_privkey, 32); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); + CHECK(ecount == 7); + + /* cleanup */ + secp256k1_context_destroy(none); + secp256k1_context_destroy(sign); + secp256k1_context_destroy(vrfy); + secp256k1_context_destroy(both); +} + void test_ecdsa_recovery_end_to_end(void) { unsigned char extra[32] = {0x00}; unsigned char privkey[32]; @@ -241,6 +381,9 @@ void test_ecdsa_recovery_edge_cases(void) { void run_recovery_tests(void) { int i; + for (i = 0; i < count; i++) { + test_ecdsa_recovery_api(); + } for (i = 0; i < 64*count; i++) { test_ecdsa_recovery_end_to_end(); } diff --git a/src/secp256k1/src/scalar_impl.h b/src/secp256k1/src/scalar_impl.h index f5b2376407bd..2690d86558a9 100644 --- a/src/secp256k1/src/scalar_impl.h +++ b/src/secp256k1/src/scalar_impl.h @@ -66,88 +66,79 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar #else secp256k1_scalar *t; int i; - /* First compute x ^ (2^N - 1) for some values of N. */ - secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; + /* First compute xN as x ^ (2^N - 1) for some values of N, + * and uM as x ^ M for some values of M. */ + secp256k1_scalar x2, x3, x6, x8, x14, x28, x56, x112, x126; + secp256k1_scalar u2, u5, u9, u11, u13; - secp256k1_scalar_sqr(&x2, x); - secp256k1_scalar_mul(&x2, &x2, x); + secp256k1_scalar_sqr(&u2, x); + secp256k1_scalar_mul(&x2, &u2, x); + secp256k1_scalar_mul(&u5, &u2, &x2); + secp256k1_scalar_mul(&x3, &u5, &u2); + secp256k1_scalar_mul(&u9, &x3, &u2); + secp256k1_scalar_mul(&u11, &u9, &u2); + secp256k1_scalar_mul(&u13, &u11, &u2); - secp256k1_scalar_sqr(&x3, &x2); - secp256k1_scalar_mul(&x3, &x3, x); - - secp256k1_scalar_sqr(&x4, &x3); - secp256k1_scalar_mul(&x4, &x4, x); - - secp256k1_scalar_sqr(&x6, &x4); + secp256k1_scalar_sqr(&x6, &u13); secp256k1_scalar_sqr(&x6, &x6); - secp256k1_scalar_mul(&x6, &x6, &x2); - - secp256k1_scalar_sqr(&x7, &x6); - secp256k1_scalar_mul(&x7, &x7, x); + secp256k1_scalar_mul(&x6, &x6, &u11); - secp256k1_scalar_sqr(&x8, &x7); - secp256k1_scalar_mul(&x8, &x8, x); + secp256k1_scalar_sqr(&x8, &x6); + secp256k1_scalar_sqr(&x8, &x8); + secp256k1_scalar_mul(&x8, &x8, &x2); - secp256k1_scalar_sqr(&x15, &x8); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x15, &x15); + secp256k1_scalar_sqr(&x14, &x8); + for (i = 0; i < 5; i++) { + secp256k1_scalar_sqr(&x14, &x14); } - secp256k1_scalar_mul(&x15, &x15, &x7); + secp256k1_scalar_mul(&x14, &x14, &x6); - secp256k1_scalar_sqr(&x30, &x15); - for (i = 0; i < 14; i++) { - secp256k1_scalar_sqr(&x30, &x30); + secp256k1_scalar_sqr(&x28, &x14); + for (i = 0; i < 13; i++) { + secp256k1_scalar_sqr(&x28, &x28); } - secp256k1_scalar_mul(&x30, &x30, &x15); + secp256k1_scalar_mul(&x28, &x28, &x14); - secp256k1_scalar_sqr(&x60, &x30); - for (i = 0; i < 29; i++) { - secp256k1_scalar_sqr(&x60, &x60); + secp256k1_scalar_sqr(&x56, &x28); + for (i = 0; i < 27; i++) { + secp256k1_scalar_sqr(&x56, &x56); } - secp256k1_scalar_mul(&x60, &x60, &x30); + secp256k1_scalar_mul(&x56, &x56, &x28); - secp256k1_scalar_sqr(&x120, &x60); - for (i = 0; i < 59; i++) { - secp256k1_scalar_sqr(&x120, &x120); + secp256k1_scalar_sqr(&x112, &x56); + for (i = 0; i < 55; i++) { + secp256k1_scalar_sqr(&x112, &x112); } - secp256k1_scalar_mul(&x120, &x120, &x60); + secp256k1_scalar_mul(&x112, &x112, &x56); - secp256k1_scalar_sqr(&x127, &x120); - for (i = 0; i < 6; i++) { - secp256k1_scalar_sqr(&x127, &x127); + secp256k1_scalar_sqr(&x126, &x112); + for (i = 0; i < 13; i++) { + secp256k1_scalar_sqr(&x126, &x126); } - secp256k1_scalar_mul(&x127, &x127, &x7); + secp256k1_scalar_mul(&x126, &x126, &x14); - /* Then accumulate the final result (t starts at x127). */ - t = &x127; - for (i = 0; i < 2; i++) { /* 0 */ + /* Then accumulate the final result (t starts at x126). */ + t = &x126; + for (i = 0; i < 3; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ + secp256k1_scalar_mul(t, t, &u5); /* 101 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ + for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u5); /* 101 */ + for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 3; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u11); /* 1011 */ + for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ + secp256k1_scalar_mul(t, t, &u11); /* 1011 */ for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } @@ -156,38 +147,26 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x3); /* 111 */ - for (i = 0; i < 4; i++) { /* 00 */ + for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 4; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u5); /* 101 */ + for (i = 0; i < 3; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ + secp256k1_scalar_mul(t, t, &x3); /* 111 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 4; i++) { /* 000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u9); /* 1001 */ + for (i = 0; i < 6; i++) { /* 000 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ + secp256k1_scalar_mul(t, t, &u5); /* 101 */ for (i = 0; i < 10; i++) { /* 0000000 */ secp256k1_scalar_sqr(t, t); } @@ -200,50 +179,34 @@ static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ - for (i = 0; i < 2; i++) { /* 0 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 3; i++) { /* 00 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, x); /* 1 */ for (i = 0; i < 5; i++) { /* 0 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x4); /* 1111 */ - for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u9); /* 1001 */ + for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 5; i++) { /* 000 */ + secp256k1_scalar_mul(t, t, &u11); /* 1011 */ + for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 4; i++) { /* 00 */ + secp256k1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 5; i++) { secp256k1_scalar_sqr(t, t); } secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 2; i++) { /* 0 */ + for (i = 0; i < 6; i++) { /* 00 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ - for (i = 0; i < 8; i++) { /* 000000 */ - secp256k1_scalar_sqr(t, t); - } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 0 */ + secp256k1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 10; i++) { /* 000000 */ secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, &x2); /* 11 */ - for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_mul(t, t, &u13); /* 1101 */ + for (i = 0; i < 4; i++) { secp256k1_scalar_sqr(t, t); } - secp256k1_scalar_mul(t, t, x); /* 1 */ + secp256k1_scalar_mul(t, t, &u9); /* 1001 */ for (i = 0; i < 6; i++) { /* 00000 */ secp256k1_scalar_sqr(t, t); } diff --git a/src/secp256k1/src/secp256k1.c b/src/secp256k1/src/secp256k1.c old mode 100755 new mode 100644 index fb8b882faafd..4f8c01655bd0 --- a/src/secp256k1/src/secp256k1.c +++ b/src/secp256k1/src/secp256k1.c @@ -424,6 +424,33 @@ int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *p return ret; } +int secp256k1_ec_privkey_negate(const secp256k1_context* ctx, unsigned char *seckey) { + secp256k1_scalar sec; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + + secp256k1_scalar_set_b32(&sec, seckey, NULL); + secp256k1_scalar_negate(&sec, &sec); + secp256k1_scalar_get_b32(seckey, &sec); + + return 1; +} + +int secp256k1_ec_pubkey_negate(const secp256k1_context* ctx, secp256k1_pubkey *pubkey) { + int ret = 0; + secp256k1_ge p; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + + ret = secp256k1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + secp256k1_ge_neg(&p, &p); + secp256k1_pubkey_save(pubkey, &p); + } + return ret; +} + int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { secp256k1_scalar term; secp256k1_scalar sec; @@ -552,10 +579,6 @@ int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey * # include "modules/ecdh/main_impl.h" #endif -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/main_impl.h" -#endif - #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/main_impl.h" #endif diff --git a/src/secp256k1/src/tests.c b/src/secp256k1/src/tests.c index 9ae7d3028130..3d9bd5ebb48d 100644 --- a/src/secp256k1/src/tests.c +++ b/src/secp256k1/src/tests.c @@ -10,6 +10,7 @@ #include #include +#include #include @@ -135,6 +136,7 @@ void random_scalar_order(secp256k1_scalar *num) { void run_context_tests(void) { secp256k1_pubkey pubkey; + secp256k1_pubkey zero_pubkey; secp256k1_ecdsa_signature sig; unsigned char ctmp[32]; int32_t ecount; @@ -149,6 +151,8 @@ void run_context_tests(void) { secp256k1_scalar msg, key, nonce; secp256k1_scalar sigr, sigs; + memset(&zero_pubkey, 0, sizeof(zero_pubkey)); + ecount = 0; ecount2 = 10; secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); @@ -201,12 +205,20 @@ void run_context_tests(void) { CHECK(ecount == 2); CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); CHECK(ecount2 == 13); - CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); + CHECK(secp256k1_ec_pubkey_negate(vrfy, &pubkey) == 1); CHECK(ecount == 2); - CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); + CHECK(secp256k1_ec_pubkey_negate(sign, &pubkey) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ec_pubkey_negate(sign, NULL) == 0); + CHECK(ecount2 == 14); + CHECK(secp256k1_ec_pubkey_negate(vrfy, &zero_pubkey) == 0); CHECK(ecount == 3); + CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); + CHECK(ecount == 3); + CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); + CHECK(ecount == 4); CHECK(secp256k1_context_randomize(sign, NULL) == 1); - CHECK(ecount2 == 13); + CHECK(ecount2 == 14); secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); secp256k1_context_set_illegal_callback(sign, NULL, NULL); @@ -1879,9 +1891,9 @@ void test_ge(void) { * * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. */ - secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); - secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); - secp256k1_fe *zinv = (secp256k1_fe *)malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs)); + secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs)); + secp256k1_fe *zinv = (secp256k1_fe *)checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs)); secp256k1_fe zf; secp256k1_fe zfi2, zfi3; @@ -1919,7 +1931,7 @@ void test_ge(void) { /* Compute z inverses. */ { - secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + secp256k1_fe *zs = checked_malloc(&ctx->error_callback, sizeof(secp256k1_fe) * (1 + 4 * runs)); for (i = 0; i < 4 * runs + 1; i++) { if (i == 0) { /* The point at infinity does not have a meaningful z inverse. Any should do. */ @@ -2020,7 +2032,7 @@ void test_ge(void) { /* Test adding all points together in random order equals infinity. */ { secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; - secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); + secp256k1_gej *gej_shuffled = (secp256k1_gej *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_gej)); for (i = 0; i < 4 * runs + 1; i++) { gej_shuffled[i] = gej[i]; } @@ -2041,9 +2053,9 @@ void test_ge(void) { /* Test batch gej -> ge conversion with and without known z ratios. */ { - secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); - secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); - secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_fe *zr = (secp256k1_fe *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_fe)); + secp256k1_ge *ge_set_table = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all = (secp256k1_ge *)checked_malloc(&ctx->error_callback, (4 * runs + 1) * sizeof(secp256k1_ge)); for (i = 0; i < 4 * runs + 1; i++) { /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ if (i < 4 * runs) { @@ -3436,6 +3448,7 @@ void test_ecdsa_end_to_end(void) { unsigned char pubkeyc[65]; size_t pubkeyclen = 65; secp256k1_pubkey pubkey; + secp256k1_pubkey pubkey_tmp; unsigned char seckey[300]; size_t seckeylen = 300; @@ -3457,6 +3470,13 @@ void test_ecdsa_end_to_end(void) { memset(&pubkey, 0, sizeof(pubkey)); CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + /* Verify negation changes the key and changes it back */ + memcpy(&pubkey_tmp, &pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); + CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) != 0); + CHECK(secp256k1_ec_pubkey_negate(ctx, &pubkey_tmp) == 1); + CHECK(memcmp(&pubkey_tmp, &pubkey, sizeof(pubkey)) == 0); + /* Verify private key import and export. */ CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); @@ -4383,10 +4403,6 @@ void run_ecdsa_openssl(void) { # include "modules/ecdh/tests_impl.h" #endif -#ifdef ENABLE_MODULE_SCHNORR -# include "modules/schnorr/tests_impl.h" -#endif - #ifdef ENABLE_MODULE_RECOVERY # include "modules/recovery/tests_impl.h" #endif @@ -4504,11 +4520,6 @@ int main(int argc, char **argv) { run_ecdsa_openssl(); #endif -#ifdef ENABLE_MODULE_SCHNORR - /* Schnorr tests */ - run_schnorr_tests(); -#endif - #ifdef ENABLE_MODULE_RECOVERY /* ECDSA pubkey recovery tests */ run_recovery_tests(); diff --git a/src/secp256k1/src/tests_exhaustive.c b/src/secp256k1/src/tests_exhaustive.c index bda6ee475c9c..b040bb0733dd 100644 --- a/src/secp256k1/src/tests_exhaustive.c +++ b/src/secp256k1/src/tests_exhaustive.c @@ -26,6 +26,11 @@ #include "secp256k1.c" #include "testrand_impl.h" +#ifdef ENABLE_MODULE_RECOVERY +#include "src/modules/recovery/main_impl.h" +#include "include/secp256k1_recovery.h" +#endif + /** stolen from tests.c */ void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { CHECK(a->infinity == b->infinity); @@ -77,7 +82,7 @@ int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned cha * function with an increased `attempt`. So if attempt > 0 this means we * need to change the nonce to avoid an infinite loop. */ if (attempt > 0) { - (*idata)++; + *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; } secp256k1_scalar_set_int(&s, *idata); secp256k1_scalar_get_b32(nonce32, &s); @@ -244,6 +249,7 @@ void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *grou for (i = 1; i < order; i++) { /* message */ for (j = 1; j < order; j++) { /* key */ for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; secp256k1_ecdsa_signature sig; secp256k1_scalar sk, msg, r, s, expected_r; unsigned char sk32[32], msg32[32]; @@ -262,6 +268,11 @@ void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *grou CHECK(r == expected_r); CHECK((k * s) % order == (i + r * j) % order || (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } } } } @@ -276,6 +287,130 @@ void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *grou */ } +#ifdef ENABLE_MODULE_RECOVERY +void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + secp256k1_fe r_dot_y_normalized; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + secp256k1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + int expected_recid; + int recid; + secp256k1_scalar_set_int(&msg, i); + secp256k1_scalar_set_int(&sk, j); + secp256k1_scalar_get_b32(sk32, &sk); + secp256k1_scalar_get_b32(msg32, &msg); + + secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); + + /* Check directly */ + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + /* In computing the recid, there is an overflow condition that is disabled in + * scalar_low_impl.h `secp256k1_scalar_set_b32` because almost every r.y value + * will exceed the group order, and our signing code always holds out for r + * values that don't overflow, so with a proper overflow check the tests would + * loop indefinitely. */ + r_dot_y_normalized = group[k].y; + secp256k1_fe_normalize(&r_dot_y_normalized); + /* Also the recovery id is flipped depending if we hit the low-s branch */ + if ((k * s) % order == (i + r * j) % order) { + expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; + } else { + expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; + } + CHECK(recid == expected_recid); + + /* Convert to a standard sig then check */ + secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } +} + +void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + /* This is essentially a copy of test_exhaustive_verify, with recovery added */ + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + secp256k1_ge nonconst_ge; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pk; + secp256k1_scalar sk_s, msg_s, r_s, s_s; + secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int recid = 0; + int k, should_verify; + unsigned char msg32[32]; + + secp256k1_scalar_set_int(&s_s, s); + secp256k1_scalar_set_int(&r_s, r); + secp256k1_scalar_set_int(&msg_s, msg); + secp256k1_scalar_set_int(&sk_s, key); + secp256k1_scalar_get_b32(msg32, &msg_s); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + secp256k1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + secp256k1_scalar_set_int(&s_times_k_s, k); + secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !secp256k1_scalar_is_high(&s_s); + + /* We would like to try recovering the pubkey and checking that it matches, + * but pubkey recovery is impossible in the exhaustive tests (the reason + * being that there are 12 nonzero r values, 12 nonzero points, and no + * overlap between the sets, so there are no valid signatures). */ + + /* Verify by converting to a standard signature and calling verify */ + secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); + secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + secp256k1_pubkey_save(&pk, &nonconst_ge); + CHECK(should_verify == + secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} +#endif + int main(void) { int i; secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; @@ -324,6 +459,12 @@ int main(void) { test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); +#ifdef ENABLE_MODULE_RECOVERY + test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); +#endif + + secp256k1_context_destroy(ctx); return 0; } diff --git a/src/secp256k1/src/util.h b/src/secp256k1/src/util.h index 4eef4ded47fd..4092a86c9175 100644 --- a/src/secp256k1/src/util.h +++ b/src/secp256k1/src/util.h @@ -57,7 +57,10 @@ static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * #endif /* Like assert(), but when VERIFY is defined, and side-effect safe. */ -#ifdef VERIFY +#if defined(COVERAGE) +#define VERIFY_CHECK(check) +#define VERIFY_SETUP(stmt) +#elif defined(VERIFY) #define VERIFY_CHECK CHECK #define VERIFY_SETUP(stmt) do { stmt; } while(0) #else From 70cd81cc8a21509c60af10420240b5b70fb7a056 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 2 Jun 2017 11:32:55 +0200 Subject: [PATCH 304/987] Merge #10423: [tests] skipped tests should clean up after themselves 930deb9 [tests] skipped tests should clean up after themselves (John Newbery) Tree-SHA512: ed486c1cf144c223efa738a66e8bb407089a23002871ef5b15c43d4c08641038a20253fc286853b457d66f37a52c81c16f7988aef90635ac262df6ce7bab9b18 --- test/functional/rpcbind_test.py | 11 ++--- .../test_framework/test_framework.py | 42 +++++++++++++------ test/functional/zmq_test.py | 9 ++-- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/test/functional/rpcbind_test.py b/test/functional/rpcbind_test.py index efc36481d183..d8ab4e6f9884 100755 --- a/test/functional/rpcbind_test.py +++ b/test/functional/rpcbind_test.py @@ -7,7 +7,7 @@ import socket import sys -from test_framework.test_framework import BitcoinTestFramework +from test_framework.test_framework import BitcoinTestFramework, SkipTest from test_framework.util import * from test_framework.netutil import * @@ -56,8 +56,7 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport): def run_test(self): # due to OS-specific network stats queries, this test works only on Linux if not sys.platform.startswith('linux'): - self.log.warning("This test can only be run on linux. Skipping test.") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("This test can only be run on linux.") # find the first non-loopback interface for testing non_loopback_ip = None for name,ip in all_interfaces(): @@ -65,15 +64,13 @@ def run_test(self): non_loopback_ip = ip break if non_loopback_ip is None: - self.log.warning("This test requires at least one non-loopback IPv4 interface. Skipping test.") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("This test requires at least one non-loopback IPv4 interface.") try: s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(("::1",1)) s.close except OSError: - self.log.warning("This test requires IPv6 support. Skipping test.") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("This test requires IPv6 support.") self.log.info("Using interface %s for testing" % non_loopback_ip) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 096f3ee8a644..18d08a32cefb 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -6,6 +6,7 @@ """Base class for RPC testing.""" from collections import deque +from enum import Enum import logging import optparse import os @@ -51,6 +52,15 @@ wait_to_sync) from .authproxy import JSONRPCException +class TestStatus(Enum): + PASSED = 1 + FAILED = 2 + SKIPPED = 3 + +TEST_EXIT_PASSED = 0 +TEST_EXIT_FAILED = 1 +TEST_EXIT_SKIPPED = 77 + class BitcoinTestFramework(object): """Base class for a bitcoin test script. @@ -67,11 +77,6 @@ class BitcoinTestFramework(object): This class also contains various public and private helper methods.""" # Methods to override in subclass test scripts. - - TEST_EXIT_PASSED = 0 - TEST_EXIT_FAILED = 1 - TEST_EXIT_SKIPPED = 77 - def __init__(self): self.num_nodes = 4 self.setup_clean_chain = False @@ -151,15 +156,18 @@ def main(self): self.options.tmpdir = tempfile.mkdtemp(prefix="test") self._start_logging() - success = False + success = TestStatus.FAILED try: self.setup_chain() self.setup_network() self.run_test() - success = True + success = TestStatus.PASSED except JSONRPCException as e: self.log.exception("JSONRPC error") + except SkipTest as e: + self.log.warning("Test Skipped: %s" % e.message) + success = TestStatus.SKIPPED except AssertionError as e: self.log.exception("Assertion failed") except KeyError as e: @@ -172,14 +180,15 @@ def main(self): if not self.options.noshutdown: self.log.info("Stopping nodes") try: - stop_nodes(self.nodes) + if self.nodes: + self.stop_nodes() except BaseException as e: success = False self.log.exception("Unexpected exception caught during shutdown") else: self.log.info("Note: dashds were not stopped and may still be running") - if not self.options.nocleanup and not self.options.noshutdown and success: + if not self.options.nocleanup and not self.options.noshutdown and success != TestStatus.FAILED: self.log.info("Cleaning up") shutil.rmtree(self.options.tmpdir) else: @@ -199,13 +208,17 @@ def main(self): except OSError: print("Opening file %s failed." % fn) traceback.print_exc() - if success: + + if success == TestStatus.PASSED: self.log.info("Tests successful") - sys.exit(self.TEST_EXIT_PASSED) + sys.exit(TEST_EXIT_PASSED) + elif success == TestStatus.SKIPPED: + self.log.info("Test skipped") + sys.exit(TEST_EXIT_SKIPPED) else: self.log.error("Test failed. Test logging available at %s/test_framework.log", self.options.tmpdir) logging.shutdown() - sys.exit(self.TEST_EXIT_FAILED) + sys.exit(TEST_EXIT_FAILED) # Public helper methods. These can be accessed by the subclass test scripts. @@ -824,6 +837,11 @@ def mine_quorum(self, expected_contributions=5, expected_complaints=0, expected_ # 2 binaries: 1 test binary, 1 ref binary # n>2 binaries: 1 test binary, n-1 ref binaries +class SkipTest(Exception): + """This exception is raised to skip a test""" + def __init__(self, message): + self.message = message + class ComparisonTestFramework(BitcoinTestFramework): def __init__(self): diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index fe7d7aa87d90..d43847361a31 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -6,9 +6,8 @@ import configparser import os import struct -import sys -from test_framework.test_framework import BitcoinTestFramework +from test_framework.test_framework import BitcoinTestFramework, SkipTest from test_framework.util import * class ZMQTest (BitcoinTestFramework): @@ -24,8 +23,7 @@ def setup_nodes(self): try: import zmq except ImportError: - self.log.warning("python3-zmq module not available. Skipping zmq tests!") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("python3-zmq module not available.") # Check that dash has been built with ZMQ enabled config = configparser.ConfigParser() @@ -34,8 +32,7 @@ def setup_nodes(self): config.read_file(open(self.options.configfile)) if not config["components"].getboolean("ENABLE_ZMQ"): - self.log.warning("dashd has not been built with zmq enabled. Skipping zmq tests!") - sys.exit(self.TEST_EXIT_SKIPPED) + raise SkipTest("dashd has not been built with zmq enabled.") self.zmqContext = zmq.Context() self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) From e353d271f07bcca1b331698611c9dc8c6b2b13d5 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 2 Jun 2017 12:08:48 +0200 Subject: [PATCH 305/987] Merge #10359: [tests] functional tests should call BitcoinTestFramework start/stop node methods 53f6775 fixup: fix nits (John Newbery) a433d8a [tests] Update start/stop node functions to be private module functions (John Newbery) d8c218f [tests] Functional tests call self.start_node(s) and self.stop_node(s) (John Newbery) Tree-SHA512: 9cc01584a5e57686b7e7cb1c4c5186ad8cc7eb650d6d4f27b06bdb5e249a10966705814bdfb22d9ff2d5d3326911e489bf3d22257d751a299c0b24b7f40bffb5 --- test/functional/abandonconflict.py | 12 +++---- test/functional/assumevalid.py | 9 +++-- test/functional/bip9-softforks.py | 2 +- test/functional/disconnect_ban.py | 6 ++-- test/functional/forknotify.py | 4 +-- test/functional/fundrawtransaction.py | 8 ++--- test/functional/import-rescan.py | 4 +-- test/functional/importmulti.py | 4 +-- test/functional/keypool.py | 2 +- test/functional/listtransactions.py | 2 +- test/functional/maxuploadtarget.py | 4 +-- test/functional/mempool_persist.py | 14 ++++---- test/functional/p2p-versionbits-warning.py | 8 ++--- test/functional/proxy_test.py | 3 +- test/functional/pruning.py | 16 ++++----- test/functional/receivedby.py | 2 +- test/functional/reindex.py | 10 ++---- test/functional/rpcbind_test.py | 8 ++--- test/functional/smartfees.py | 6 ++-- .../test_framework/test_framework.py | 18 +++++----- test/functional/test_framework/util.py | 36 +++++++++++-------- test/functional/wallet-accounts.py | 4 +-- test/functional/wallet-dump.py | 4 +-- test/functional/wallet-hd.py | 6 ++-- test/functional/wallet.py | 20 +++++------ test/functional/walletbackup.py | 12 +++---- test/functional/zapwallettxes.py | 10 +++--- test/functional/zmq_test.py | 2 +- 28 files changed, 115 insertions(+), 121 deletions(-) diff --git a/test/functional/abandonconflict.py b/test/functional/abandonconflict.py index 974875764168..c87c02492d7c 100755 --- a/test/functional/abandonconflict.py +++ b/test/functional/abandonconflict.py @@ -73,8 +73,8 @@ def run_test(self): # Restart the node with a higher min relay fee so the parent tx is no longer in mempool # TODO: redo with eviction - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) # Verify txs no longer in either node's mempool assert_equal(len(self.nodes[0].getrawmempool()), 0) @@ -100,8 +100,8 @@ def run_test(self): balance = newbalance # Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.00001"]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.00001"]) assert_equal(len(self.nodes[0].getrawmempool()), 0) assert_equal(self.nodes[0].getbalance(), balance) @@ -120,8 +120,8 @@ def run_test(self): balance = newbalance # Remove using high relay fee again - stop_node(self.nodes[0],0) - self.nodes[0]=start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-minrelaytxfee=0.0001"]) assert_equal(len(self.nodes[0].getrawmempool()), 0) newbalance = self.nodes[0].getbalance() assert_equal(newbalance, balance - Decimal("24.9996")) diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index d0ca004666d8..01ea35972c69 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -45,8 +45,7 @@ msg_headers) from test_framework.script import (CScript, OP_TRUE) from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import (start_node, p2p_port, assert_equal, get_mocktime, set_mocktime, set_node_times) - +from test_framework.util import (p2p_port, assert_equal, get_mocktime, set_mocktime, set_node_times) class BaseNode(NodeConnCB): def send_header_for_blocks(self, new_blocks): @@ -64,7 +63,7 @@ def setup_network(self): # Start node0. We don't start the other nodes yet since # we need to pre-mine a block with an invalid transaction # signature so we can pass in the block hash as assumevalid. - self.nodes = [start_node(0, self.options.tmpdir, ["-dip3params=9000:9000", "-checkblockindex=0"])] + self.nodes = [self.start_node(0, self.options.tmpdir, ["-dip3params=9000:9000", "-checkblockindex=0"])] def send_blocks_until_disconnected(self, node): """Keep sending blocks to the node until we're disconnected.""" @@ -169,14 +168,14 @@ def run_test(self): height += 1 # Start node1 and node2 with assumevalid so they accept a block with a bad signature. - self.nodes.append(start_node(1, self.options.tmpdir, + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-assumevalid=" + hex(block102.sha256), "-dip3params=9000:9000", "-checkblockindex=0"])) node1 = BaseNode() # connects to node1 connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], node1)) node1.add_connection(connections[1]) node1.wait_for_verack() - self.nodes.append(start_node(2, self.options.tmpdir, + self.nodes.append(self.start_node(2, self.options.tmpdir, ["-assumevalid=" + hex(block102.sha256), "-dip3params=9000:9000", "-checkblockindex=0"])) node2 = BaseNode() # connects to node2 connections.append(NodeConn('127.0.0.1', p2p_port(2), self.nodes[2], node2)) diff --git a/test/functional/bip9-softforks.py b/test/functional/bip9-softforks.py index cb347617f8fa..a889cfc48eae 100755 --- a/test/functional/bip9-softforks.py +++ b/test/functional/bip9-softforks.py @@ -238,7 +238,7 @@ def test_BIP(self, bipName, activated_version, invalidate, invalidatePostSignatu # Restart all self.test.clear_all_connections() - stop_nodes(self.nodes) + self.stop_nodes() shutil.rmtree(self.options.tmpdir + "/node0") self.setup_chain() self.setup_network() diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py index 2a9244e9e383..bf513c841cab 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/disconnect_ban.py @@ -10,8 +10,6 @@ from test_framework.util import (assert_equal, assert_raises_jsonrpc, connect_nodes_bi, - start_node, - stop_node, set_mocktime, get_mocktime, set_node_times, @@ -73,9 +71,9 @@ def run_test(self): self.nodes[1].setmocktime(old_time + 3) assert_equal(len(self.nodes[1].listbanned()), 3) - stop_node(self.nodes[1], 1) + self.stop_node(1) - self.nodes[1] = start_node(1, self.options.tmpdir) + self.nodes[1] = self.start_node(1, self.options.tmpdir) listAfterShutdown = self.nodes[1].listbanned() assert_equal("127.0.0.0/24", listAfterShutdown[0]['address']) assert_equal("127.0.0.0/32", listAfterShutdown[1]['address']) diff --git a/test/functional/forknotify.py b/test/functional/forknotify.py index 9db61c8350f9..3bcf0a679511 100755 --- a/test/functional/forknotify.py +++ b/test/functional/forknotify.py @@ -21,10 +21,10 @@ def setup_network(self): self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") with open(self.alert_filename, 'w', encoding='utf8'): pass # Just open then close to create zero-length file - self.nodes.append(start_node(0, self.options.tmpdir, + self.nodes.append(self.start_node(0, self.options.tmpdir, ["-blockversion=2", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""])) # Node1 mines block.version=211 blocks - self.nodes.append(start_node(1, self.options.tmpdir, + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-blockversion=211"])) connect_nodes(self.nodes[1], 0) diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index 14fc51fca20a..b8a57aae4c19 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -449,13 +449,13 @@ def run_test(self): ############################################################ # locked wallet test + self.stop_node(0) + self.stop_node(2) + self.stop_node(3) self.nodes[1].encryptwallet("test") self.nodes.pop(1) - stop_node(self.nodes[0], 0) - stop_node(self.nodes[1], 2) - stop_node(self.nodes[2], 3) - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [['-usehd=0']] * self.num_nodes) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, [['-usehd=0']] * self.num_nodes) # This test is not meant to test fee estimation and we'd like # to be sure all txs are sent at a consistent desired feerate for node in self.nodes: diff --git a/test/functional/import-rescan.py b/test/functional/import-rescan.py index 659baa61c408..011cd58d8953 100755 --- a/test/functional/import-rescan.py +++ b/test/functional/import-rescan.py @@ -21,7 +21,7 @@ from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import (start_nodes, connect_nodes, sync_blocks, assert_equal, set_node_times) +from test_framework.util import (connect_nodes, sync_blocks, assert_equal, set_node_times) import collections import enum @@ -122,7 +122,7 @@ def setup_network(self): # txindex is enabled by default in Dash and needs to be disabled for import-rescan.py extra_args[i] += ["-prune=1", "-txindex=0", "-reindex-chainstate"] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args) for i in range(1, self.num_nodes): connect_nodes(self.nodes[i], 0) diff --git a/test/functional/importmulti.py b/test/functional/importmulti.py index 9e3491c428f5..e83e85de138e 100755 --- a/test/functional/importmulti.py +++ b/test/functional/importmulti.py @@ -428,8 +428,8 @@ def run_test (self): # restart nodes to check for proper serialization/deserialization of watch only address - stop_nodes(self.nodes) - self.nodes = start_nodes(2, self.options.tmpdir) + self.stop_nodes() + self.nodes = self.start_nodes(2, self.options.tmpdir) address_assert = self.nodes[1].validateaddress(watchonly_address) assert_equal(address_assert['iswatchonly'], True) assert_equal(address_assert['ismine'], False) diff --git a/test/functional/keypool.py b/test/functional/keypool.py index 72f34d16b536..42186ea58eb5 100755 --- a/test/functional/keypool.py +++ b/test/functional/keypool.py @@ -21,7 +21,7 @@ def run_test(self): nodes[0].encryptwallet('test') bitcoind_processes[0].wait() # Restart node 0 - nodes[0] = start_node(0, self.options.tmpdir, ['-usehd=0']) + nodes[0] = self.start_node(0, self.options.tmpdir, ['-usehd=0']) # Keep creating keys addr = nodes[0].getnewaddress() diff --git a/test/functional/listtransactions.py b/test/functional/listtransactions.py index 4642c213bd27..87956c0bf393 100755 --- a/test/functional/listtransactions.py +++ b/test/functional/listtransactions.py @@ -24,7 +24,7 @@ def __init__(self): def setup_nodes(self): #This test requires mocktime set_cache_mocktime() - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): # Simple send, 0 to 1: diff --git a/test/functional/maxuploadtarget.py b/test/functional/maxuploadtarget.py index 1a8f2d3b0555..f7a7fc1e6e18 100755 --- a/test/functional/maxuploadtarget.py +++ b/test/functional/maxuploadtarget.py @@ -151,8 +151,8 @@ def run_test(self): #stop and start node 0 with 1MB maxuploadtarget, whitelist 127.0.0.1 self.log.info("Restarting nodes with -whitelist=127.0.0.1") - stop_node(self.nodes[0], 0) - self.nodes[0] = start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1", "-maxuploadtarget=1", "-blockmaxsize=999000", "-maxtipage="+str(2*60*60*24*7)]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-whitelist=127.0.0.1", "-maxuploadtarget=1", "-blockmaxsize=999000", "-maxtipage="+str(2*60*60*24*7)]) #recreate/reconnect a test node test_nodes = [TestNode()] diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index 39dc2e2bff6a..90eb6707cc1d 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -63,27 +63,27 @@ def run_test(self): assert_equal(len(self.nodes[1].getrawmempool()), 5) self.log.debug("Stop-start node0 and node1. Verify that node0 has the transactions in its mempool and node1 does not.") - stop_nodes(self.nodes) + self.stop_nodes() self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir)) + self.nodes.append(self.start_node(0, self.options.tmpdir)) + self.nodes.append(self.start_node(1, self.options.tmpdir)) # Give dashd a second to reload the mempool time.sleep(1) assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) assert_equal(len(self.nodes[1].getrawmempool()), 0) self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.") - stop_nodes(self.nodes) + self.stop_nodes() self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir, ["-persistmempool=0"])) + self.nodes.append(self.start_node(0, self.options.tmpdir, ["-persistmempool=0"])) # Give dashd a second to reload the mempool time.sleep(1) assert_equal(len(self.nodes[0].getrawmempool()), 0) self.log.debug("Stop-start node0. Verify that it has the transactions in its mempool.") - stop_nodes(self.nodes) + self.stop_nodes() self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir)) + self.nodes.append(self.start_node(0, self.options.tmpdir)) assert wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) if __name__ == '__main__': diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py index 41921fe14e3c..df7e8ce5c163 100755 --- a/test/functional/p2p-versionbits-warning.py +++ b/test/functional/p2p-versionbits-warning.py @@ -108,22 +108,22 @@ def run_test(self): # is cleared, and restart the node. This should move the versionbit state # to ACTIVE. self.nodes[0].generate(VB_PERIOD) - stop_nodes(self.nodes) + self.stop_nodes() # Empty out the alert file with open(self.alert_filename, 'w', encoding='utf8') as _: pass - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) # Connecting one block should be enough to generate an error. self.nodes[0].generate(1) assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getinfo()["errors"]) assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["errors"]) assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"]) - stop_nodes(self.nodes) + self.stop_nodes() self.test_versionbits_in_alert_file() # Test framework expects the node to still be running... - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, self.extra_args) if __name__ == '__main__': VersionBitsWarningTest().main() diff --git a/test/functional/proxy_test.py b/test/functional/proxy_test.py index 69384d9d85af..ae6f843ddce7 100755 --- a/test/functional/proxy_test.py +++ b/test/functional/proxy_test.py @@ -35,7 +35,6 @@ from test_framework.util import ( PORT_MIN, PORT_RANGE, - start_nodes, assert_equal, ) from test_framework.netutil import test_ipv6_local @@ -90,7 +89,7 @@ def setup_nodes(self): ] if self.have_ipv6: args[3] = ['-listen', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion'] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args) def node_test(self, node, proxies, auth, test_onion=True): rv = [] diff --git a/test/functional/pruning.py b/test/functional/pruning.py index f499bdab820e..9ee09c1a72a3 100755 --- a/test/functional/pruning.py +++ b/test/functional/pruning.py @@ -98,7 +98,7 @@ def create_chain_with_staleblocks(self): # Node 2 stays connected, so it hears about the stale blocks and then reorg's when node0 reconnects # Stopping node 0 also clears its mempool, so it doesn't have node1's transactions to accidentally mine self.stop_node(0) - self.nodes[0]=start_node(0, self.options.tmpdir, self.full_node_default_args, timewait=900) + self.nodes[0]=self.start_node(0, self.options.tmpdir, self.full_node_default_args, timewait=900) # Mine 24 blocks in node 1 for i in range(24): if j == 0: @@ -126,7 +126,7 @@ def reorg_test(self): # Reboot node 1 to clear its mempool (hopefully make the invalidate faster) # Lower the block max size so we don't keep mining all our big mempool transactions (from disconnected blocks) self.stop_node(1) - self.nodes[1]=start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) + self.nodes[1] = self.start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) height = self.nodes[1].getblockcount() self.log.info("Current block height: %d" % height) @@ -149,7 +149,7 @@ def reorg_test(self): # Reboot node1 to clear those giant tx's from mempool self.stop_node(1) - self.nodes[1]=start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) + self.nodes[1] = self.start_node(1, self.options.tmpdir, ["-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900) self.log.info("Generating new longer chain of 300 more blocks") self.nodes[1].generate(300) @@ -227,13 +227,13 @@ def reorg_back(self): def manual_test(self, node_number, use_timestamp): # at this point, node has 995 blocks and has not yet run in prune mode - node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0"], stderr=sys.stdout, timewait=900) + node = self.nodes[node_number] = self.start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0"], stderr=sys.stdout, timewait=900) assert_equal(node.getblockcount(), 995) assert_raises_jsonrpc(-1, "not in prune mode", node.pruneblockchain, 500) self.stop_node(node_number) # now re-start in manual pruning mode - node = self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=1"], stderr=sys.stdout, timewait=900) + node = self.nodes[node_number] = self.start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=1"], stderr=sys.stdout, timewait=900) assert_equal(node.getblockcount(), 995) def height(index): @@ -307,7 +307,7 @@ def has_block(index): # stop node, start back up with auto-prune at 550MB, make sure still runs self.stop_node(node_number) - self.nodes[node_number] = start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout, timewait=900) + self.nodes[node_number] = self.start_node(node_number, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout, timewait=900) self.log.info("Success") @@ -315,7 +315,7 @@ def wallet_test(self): # check that the pruning node's wallet is still in good shape self.log.info("Stop and start pruning node to trigger wallet rescan") self.stop_node(2) - start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) + self.start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) self.log.info("Success") # check that wallet loads loads successfully when restarting a pruned node after IBD. @@ -325,7 +325,7 @@ def wallet_test(self): nds = [self.nodes[0], self.nodes[5]] sync_blocks(nds, wait=5, timeout=300) self.stop_node(5) #stop and start to trigger rescan - start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) + self.start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) self.log.info("Success") def run_test(self): diff --git a/test/functional/receivedby.py b/test/functional/receivedby.py index 9912f7b9ea72..c4b6ce4b72ed 100755 --- a/test/functional/receivedby.py +++ b/test/functional/receivedby.py @@ -32,7 +32,7 @@ def __init__(self): def setup_nodes(self): #This test requires mocktime set_cache_mocktime() - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir) def run_test(self): ''' diff --git a/test/functional/reindex.py b/test/functional/reindex.py index 8b8c5f3e710a..b446baa04dee 100755 --- a/test/functional/reindex.py +++ b/test/functional/reindex.py @@ -10,11 +10,7 @@ """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import ( - start_nodes, - stop_nodes, - assert_equal, -) +from test_framework.util import assert_equal import time class ReindexTest(BitcoinTestFramework): @@ -27,9 +23,9 @@ def __init__(self): def reindex(self, justchainstate=False): self.nodes[0].generate(3) blockcount = self.nodes[0].getblockcount() - stop_nodes(self.nodes) + self.stop_nodes() extra_args = [["-reindex-chainstate" if justchainstate else "-reindex", "-checkblockindex=1"]] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args) while self.nodes[0].getblockcount() < blockcount: time.sleep(0.1) assert_equal(self.nodes[0].getblockcount(), blockcount) diff --git a/test/functional/rpcbind_test.py b/test/functional/rpcbind_test.py index d8ab4e6f9884..5336cf2ec89f 100755 --- a/test/functional/rpcbind_test.py +++ b/test/functional/rpcbind_test.py @@ -36,10 +36,10 @@ def run_bind_test(self, allow_ips, connect_to, addresses, expected): if allow_ips: base_args += ['-rpcallowip=' + x for x in allow_ips] binds = ['-rpcbind='+addr for addr in addresses] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args + binds], connect_to) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, [base_args + binds], connect_to) pid = bitcoind_processes[0].pid assert_equal(set(get_bind_addrs(pid)), set(expected)) - stop_nodes(self.nodes) + self.stop_nodes() def run_allowip_test(self, allow_ips, rpchost, rpcport): ''' @@ -47,11 +47,11 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport): at a non-localhost IP. ''' base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args]) + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, [base_args]) # connect to node through non-loopback interface node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0) node.getnetworkinfo() - stop_nodes(self.nodes) + self.stop_nodes() def run_test(self): # due to OS-specific network stats queries, this test works only on Linux diff --git a/test/functional/smartfees.py b/test/functional/smartfees.py index 72d00f9acb3d..e0bfebeeff99 100755 --- a/test/functional/smartfees.py +++ b/test/functional/smartfees.py @@ -155,7 +155,7 @@ def setup_network(self): """ self.nodes = [] # Use node0 to mine blocks for input splitting - self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000", + self.nodes.append(self.start_node(0, self.options.tmpdir, ["-maxorphantx=1000", "-whitelist=127.0.0.1"])) self.log.info("This test is time consuming, please be patient") @@ -191,7 +191,7 @@ def setup_network(self): # Node1 mines small blocks but that are bigger than the expected transaction rate. # NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes, # (17k is room enough for 110 or so transactions) - self.nodes.append(start_node(1, self.options.tmpdir, + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-blockmaxsize=17000", "-maxorphantx=1000"])) connect_nodes(self.nodes[1], 0) @@ -200,7 +200,7 @@ def setup_network(self): # produces too small blocks (room for only 55 or so transactions) node2args = ["-blockmaxsize=8000", "-maxorphantx=1000"] - self.nodes.append(start_node(2, self.options.tmpdir, node2args)) + self.nodes.append(self.start_node(2, self.options.tmpdir, node2args)) connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[2], 1) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 18d08a32cefb..16cf71c345d0 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -41,10 +41,10 @@ set_mocktime, set_node_times, satoshi_round, - start_node, - start_nodes, - stop_node, - stop_nodes, + _start_node, + _start_nodes, + _stop_node, + _stop_nodes, sync_blocks, sync_mempools, sync_masternodes, @@ -108,7 +108,7 @@ def setup_nodes(self, stderr=None): extra_args = None if hasattr(self, "extra_args"): extra_args = self.extra_args - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args, stderr=stderr) + self.nodes = _start_nodes(self.num_nodes, self.options.tmpdir, extra_args, stderr=stderr) def run_test(self): raise NotImplementedError @@ -223,16 +223,16 @@ def main(self): # Public helper methods. These can be accessed by the subclass test scripts. def start_node(self, i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): - return start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr) + return _start_node(i, dirname, extra_args, rpchost, timewait, binary, stderr) def start_nodes(self, num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): - return start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary, stderr) + return _start_nodes(num_nodes, dirname, extra_args, rpchost, timewait, binary, stderr) def stop_node(self, num_node): - stop_node(self.nodes[num_node], num_node) + _stop_node(self.nodes[num_node], num_node) def stop_nodes(self): - stop_nodes(self.nodes) + _stop_nodes(self.nodes) def split_network(self): """ diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 247d702bb5ec..f062e32da22f 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -251,10 +251,10 @@ def wait_for_bitcoind_start(process, url, i): time.sleep(0.25) -def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): - """ - Start a dashd and return RPC connection to it - """ +def _start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): + """Start a dashd and return RPC connection to it + + This function should only be called from within test_framework, not by individual test scripts.""" datadir = os.path.join(dirname, "node"+str(i)) if binary is None: binary = os.getenv("BITCOIND", "dashd") @@ -279,8 +279,8 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary= def assert_start_raises_init_error(i, dirname, extra_args=None, expected_msg=None): with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr: try: - node = start_node(i, dirname, extra_args, stderr=log_stderr) - stop_node(node, i) + node = _start_node(i, dirname, extra_args, stderr=log_stderr) + _stop_node(node, i) except Exception as e: assert 'dashd exited' in str(e) #node must have shutdown if expected_msg is not None: @@ -295,10 +295,10 @@ def assert_start_raises_init_error(i, dirname, extra_args=None, expected_msg=Non assert_msg = "dashd should have exited with expected error " + expected_msg raise AssertionError(assert_msg) -def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): - """ - Start multiple dashds, return RPC connections to them - """ +def _start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None, binary=None, stderr=None): + """Start multiple dashds, return RPC connections to them + + This function should only be called from within test_framework, not by individual test scripts.""" if extra_args is None: extra_args = [ None for _ in range(num_nodes) ] if binary is None: binary = [ None for _ in range(num_nodes) ] assert_equal(len(extra_args), num_nodes) @@ -306,9 +306,9 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, timewait=None rpcs = [] try: for i in range(num_nodes): - rpcs.append(start_node(i, dirname, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=stderr)) + rpcs.append(_start_node(i, dirname, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=stderr)) except: # If one node failed to start, stop the others - stop_nodes(rpcs) + _stop_nodes(rpcs) raise return rpcs @@ -335,7 +335,10 @@ def wait_node(i): assert_equal(return_code, 0) del bitcoind_processes[i] -def stop_node(node, i, wait=True): +def _stop_node(node, i, wait=True): + """Stop a bitcoind test node + + This function should only be called from within test_framework, not by individual test scripts.""" logger.debug("Stopping node %d" % i) try: node.stop() @@ -344,9 +347,12 @@ def stop_node(node, i, wait=True): if wait: wait_node(i) -def stop_nodes(nodes, fast=True): +def _stop_nodes(nodes, fast=True): + """Stop multiple bitcoind test nodes + + This function should only be called from within test_framework, not by individual test scripts.""" for i, node in enumerate(nodes): - stop_node(node, i, not fast) + _stop_node(node, i, not fast) if fast: for i, node in enumerate(nodes): wait_node(i) diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet-accounts.py index 2cdaa37de86e..c996c89ea3cc 100755 --- a/test/functional/wallet-accounts.py +++ b/test/functional/wallet-accounts.py @@ -14,9 +14,7 @@ """ from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import ( - assert_equal, -) +from test_framework.util import assert_equal class WalletAccountsTest(BitcoinTestFramework): diff --git a/test/functional/wallet-dump.py b/test/functional/wallet-dump.py index 67e4f3f71201..b31a082c38bc 100755 --- a/test/functional/wallet-dump.py +++ b/test/functional/wallet-dump.py @@ -70,7 +70,7 @@ def setup_network(self): # longer than the default 30 seconds due to an expensive # CWallet::TopUpKeyPool call, and the encryptwallet RPC made later in # the test often takes even longer. - self.nodes = start_nodes(self.num_nodes, os.path.join(self.options.tmpdir, "hd"), self.extra_args, timewait=60, stderr=sys.stdout) + self.nodes = self.start_nodes(self.num_nodes, os.path.join(self.options.tmpdir, "hd"), self.extra_args, timewait=60, stderr=sys.stdout) def run_test (self): tmpdir = os.path.join(self.options.tmpdir, "hd") @@ -97,7 +97,7 @@ def run_test (self): #encrypt wallet, restart, unlock and dump self.nodes[0].encryptwallet('test') bitcoind_processes[0].wait() - self.nodes[0] = start_node(0, tmpdir, self.extra_args[0]) + self.nodes[0] = self.start_node(0, tmpdir, self.extra_args[0]) self.nodes[0].walletpassphrase('test', 10) # Should be a no-op: self.nodes[0].keypoolrefill() diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index 022cfb19fc2b..e5016e25de64 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -24,7 +24,7 @@ def run_test (self): # Make sure can't switch off usehd after wallet creation self.stop_node(1) assert_start_raises_init_error(1, self.options.tmpdir, ['-usehd=0'], 'already existing HD wallet') - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1], stderr=sys.stdout) + self.nodes[1] = self.start_node(1, self.options.tmpdir, self.extra_args[1], stderr=sys.stdout) connect_nodes_bi(self.nodes, 0, 1) # Make sure we use hd, keep chainid @@ -71,7 +71,7 @@ def run_test (self): stop_node(self.nodes[1],1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1], stderr=sys.stdout) + self.nodes[1] = self.start_node(1, self.options.tmpdir, self.extra_args[1], stderr=sys.stdout) #connect_nodes_bi(self.nodes, 0, 1) # Assert that derivation is deterministic @@ -85,7 +85,7 @@ def run_test (self): # Needs rescan self.stop_node(1) - self.nodes[1] = start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan'], stderr=sys.stdout) + self.nodes[1] = self.start_node(1, self.options.tmpdir, self.extra_args[1] + ['-rescan'], stderr=sys.stdout) #connect_nodes_bi(self.nodes, 0, 1) assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) diff --git a/test/functional/wallet.py b/test/functional/wallet.py index 70ed64390f15..d5e59c426124 100755 --- a/test/functional/wallet.py +++ b/test/functional/wallet.py @@ -21,7 +21,7 @@ def __init__(self): self.extra_args = [['-usehd={:d}'.format(i%2==0)] for i in range(4)] def setup_network(self): - self.nodes = start_nodes(3, self.options.tmpdir, self.extra_args[:3], stderr=sys.stdout) + self.nodes = self.start_nodes(3, self.options.tmpdir, self.extra_args[:3], stderr=sys.stdout) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -178,7 +178,7 @@ def run_test(self): txid2 = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1) sync_mempools(self.nodes) - self.nodes.append(start_node(3, self.options.tmpdir, self.extra_args[3], stderr=sys.stdout)) + self.nodes.append(self.start_node(3, self.options.tmpdir, self.extra_args[3], stderr=sys.stdout)) connect_nodes_bi(self.nodes, 0, 3) sync_blocks(self.nodes) @@ -221,8 +221,8 @@ def run_test(self): assert(found) #do some -walletbroadcast tests - stop_nodes(self.nodes) - self.nodes = start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]]) + self.stop_nodes() + self.nodes = self.start_nodes(3, self.options.tmpdir, [["-walletbroadcast=0"],["-walletbroadcast=0"],["-walletbroadcast=0"]]) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -246,8 +246,8 @@ def run_test(self): txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2) #restart the nodes with -walletbroadcast=1 - stop_nodes(self.nodes) - self.nodes = start_nodes(3, self.options.tmpdir) + self.stop_nodes() + self.nodes = self.start_nodes(3, self.options.tmpdir) connect_nodes_bi(self.nodes,0,1) connect_nodes_bi(self.nodes,1,2) connect_nodes_bi(self.nodes,0,2) @@ -348,9 +348,9 @@ def run_test(self): chainlimit = 6 for m in maintenance: self.log.info("check " + m) - stop_nodes(self.nodes) + self.stop_nodes() # set lower ancestor limit for later - self.nodes = start_nodes(3, self.options.tmpdir, [[m, "-limitancestorcount="+str(chainlimit)]] * 3) + self.nodes = self.start_nodes(3, self.options.tmpdir, [[m, "-limitancestorcount="+str(chainlimit)]] * 3) while m == '-reindex' and [block_count] * 3 != [self.nodes[i].getblockcount() for i in range(3)]: # reindex will leave rpc warm up "early"; Wait for it to finish time.sleep(0.1) @@ -397,8 +397,8 @@ def run_test(self): # Try with walletrejectlongchains # Double chain limit but require combining inputs, so we pass SelectCoinsMinConf - stop_node(self.nodes[0],0) - self.nodes[0] = start_node(0, self.options.tmpdir, ["-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)]) + self.stop_node(0) + self.nodes[0] = self.start_node(0, self.options.tmpdir, ["-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)]) # wait for loadmempool timeout = 10 diff --git a/test/functional/walletbackup.py b/test/functional/walletbackup.py index 2ecd7ee19f93..cf69e317bfab 100755 --- a/test/functional/walletbackup.py +++ b/test/functional/walletbackup.py @@ -77,18 +77,18 @@ def do_one_round(self): # As above, this mirrors the original bash test. def start_three(self): - self.nodes[0] = start_node(0, self.options.tmpdir) - self.nodes[1] = start_node(1, self.options.tmpdir) - self.nodes[2] = start_node(2, self.options.tmpdir) + self.nodes[0] = self.start_node(0, self.options.tmpdir) + self.nodes[1] = self.start_node(1, self.options.tmpdir) + self.nodes[2] = self.start_node(2, self.options.tmpdir) connect_nodes(self.nodes[0], 3) connect_nodes(self.nodes[1], 3) connect_nodes(self.nodes[2], 3) connect_nodes(self.nodes[2], 0) def stop_three(self): - stop_node(self.nodes[0], 0) - stop_node(self.nodes[1], 1) - stop_node(self.nodes[2], 2) + self.stop_node(0) + self.stop_node(1) + self.stop_node(2) def erase_three(self): os.remove(self.options.tmpdir + "/node0/regtest/wallet.dat") diff --git a/test/functional/zapwallettxes.py b/test/functional/zapwallettxes.py index bd5f024d6578..222be0130c5b 100755 --- a/test/functional/zapwallettxes.py +++ b/test/functional/zapwallettxes.py @@ -58,18 +58,16 @@ def run_test (self): assert_equal(tx3['txid'], txid3) #tx3 must be available (unconfirmed) #restart bitcoind - self.nodes[0].stop() - bitcoind_processes[0].wait() - self.nodes[0] = start_node(0,self.options.tmpdir) + self.stop_node(0) + self.nodes[0] = self.start_node(0,self.options.tmpdir) tx3 = self.nodes[0].gettransaction(txid3) assert_equal(tx3['txid'], txid3) #tx must be available (unconfirmed) - self.nodes[0].stop() - bitcoind_processes[0].wait() + self.stop_node(0) #restart bitcoind with zapwallettxes - self.nodes[0] = start_node(0,self.options.tmpdir, ["-zapwallettxes=1"]) + self.nodes[0] = self.start_node(0,self.options.tmpdir, ["-zapwallettxes=1"]) assert_raises(JSONRPCException, self.nodes[0].gettransaction, [txid3]) #there must be a expection because the unconfirmed wallettx0 must be gone by now diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index d43847361a31..cc357372ebc4 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -39,7 +39,7 @@ def setup_nodes(self): self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx") self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port) - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ ['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)], [], [], From f59e5e67f0b522d4ae0d46b99b7a5f1fb07dbd54 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 2 Jun 2017 16:03:21 -0700 Subject: [PATCH 306/987] Merge #10500: Avoid CWalletTx copies in GetAddressBalances and GetAddressGroupings b9b814a38 Avoid CWalletTx copies in GetAddressBalances and GetAddressGroupings (Russell Yanofsky) Tree-SHA512: 96a0612ca460ba1bfb3921f3aa348400fd3afa12c40f2ca1f3f04068b1574fe824d577e0123013d8898a4990084316dc1dfb541331849f0996ceff7f4eb25e6b --- src/wallet/wallet.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 70e92f9d64ab..6c623bb0669d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4270,9 +4270,9 @@ std::map CWallet::GetAddressBalances() { LOCK(cs_wallet); - BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + for (const auto& walletEntry : mapWallet) { - CWalletTx *pcoin = &walletEntry.second; + const CWalletTx *pcoin = &walletEntry.second; if (!pcoin->IsTrusted()) continue; @@ -4310,9 +4310,9 @@ std::set< std::set > CWallet::GetAddressGroupings() std::set< std::set > groupings; std::set grouping; - BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet) + for (const auto& walletEntry : mapWallet) { - CWalletTx *pcoin = &walletEntry.second; + const CWalletTx *pcoin = &walletEntry.second; if (pcoin->tx->vin.size() > 0) { From 40cec429b3d74a2c6e03d90125a35349522be5fa Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 4 Jun 2017 11:29:34 -0700 Subject: [PATCH 307/987] Merge #10471: Denote functions CNode::GetRecvVersion() and CNode::GetRefCount() as const 5f672ca8c net: Denote some CNode functions const (Pavlos Antoniou) Tree-SHA512: f6d13d8002a4145fd87b34b35a739284e4a9b1af834bba109d324eccddb684eccb817553ba76102eb5b5819cab37f938b4ba74fdbda7c5386d00747b3024cd81 --- src/net.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net.h b/src/net.h index 59b82277622a..5e2fecebb58a 100644 --- a/src/net.h +++ b/src/net.h @@ -882,7 +882,7 @@ class CNode return nMyStartingHeight; } - int GetRefCount() + int GetRefCount() const { assert(nRefCount >= 0); return nRefCount; @@ -894,7 +894,7 @@ class CNode { nRecvVersion = nVersionIn; } - int GetRecvVersion() + int GetRecvVersion() const { return nRecvVersion; } From 44a55019b4c2cb90a5b254a1ef2523b64c41304e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 5 Jun 2017 15:39:11 +0200 Subject: [PATCH 308/987] Merge #10478: rpc: Add listen address to incoming connections in `getpeerinfo` 3457331 test: Add test for `getpeerinfo` `bindaddr` field (Wladimir J. van der Laan) a7e3c28 rpc: Add listen address to incoming connections in `getpeerinfo` (Wladimir J. van der Laan) Tree-SHA512: bcd58bca2d35fc9698e958e22a7cf8268a6c731a3a309df183f43fc5e725a88ae09f006290fde7aa03cee9a403e2e25772097409677cedbce8f267e01e9040f6 --- src/net.cpp | 33 +++++++++++++++++++++++++++------ src/net.h | 10 +++++++++- src/rpc/net.cpp | 5 ++++- src/test/DoS_tests.cpp | 8 ++++---- src/test/net_tests.cpp | 4 ++-- test/functional/net.py | 7 +++++++ 6 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 4923120058f9..7a09e5467284 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -351,6 +351,22 @@ bool CConnman::CheckIncomingNonce(uint64_t nonce) return true; } +/** Get the bind address for a socket as CAddress */ +static CAddress GetBindAddress(SOCKET sock) +{ + CAddress addr_bind; + struct sockaddr_storage sockaddr_bind; + socklen_t sockaddr_bind_len = sizeof(sockaddr_bind); + if (sock != INVALID_SOCKET) { + if (!getsockname(sock, (struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) { + addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind); + } else { + LogPrint(BCLog::NET, "Warning: getsockname failed\n"); + } + } + return addr_bind; +} + CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure) { if (pszDest == NULL) { @@ -406,8 +422,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo // Add node NodeId id = GetNewNodeId(); uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); - CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, pszDest ? pszDest : "", false); - + CAddress addr_bind = GetBindAddress(hSocket); + CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", false); pnode->nServicesExpected = ServiceFlags(addrConnect.nServices & nRelevantServices); pnode->AddRef(); @@ -646,6 +662,7 @@ void CNode::copyStats(CNodeStats &stats) stats.nodeid = this->GetId(); X(nServices); X(addr); + X(addrBind); { LOCK(cs_filter); X(fRelayTxes); @@ -1086,9 +1103,11 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { int nVerifiedInboundMasternodes = 0; int nMaxInbound = nMaxConnections - (nMaxOutbound + nMaxFeeler); - if (hSocket != INVALID_SOCKET) - if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) + if (hSocket != INVALID_SOCKET) { + if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) { LogPrintf("Warning: Unknown socket family\n"); + } + } bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr); { @@ -1161,8 +1180,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { NodeId id = GetNewNodeId(); uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); + CAddress addr_bind = GetBindAddress(hSocket); - CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, "", true); + CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", true); pnode->AddRef(); pnode->fWhitelisted = whitelisted; GetNodeSignals().InitializeNode(pnode, *this); @@ -3062,11 +3082,12 @@ int CConnman::GetBestHeight() const unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; } unsigned int CConnman::GetSendBufferSize() const{ return nSendBufferMaxSize; } -CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const std::string& addrNameIn, bool fInboundIn) : +CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string& addrNameIn, bool fInboundIn) : nTimeConnected(GetSystemTimeInSeconds()), nTimeFirstMessageReceived(0), fFirstMessageIsMNAUTH(false), addr(addrIn), + addrBind(addrBindIn), fInbound(fInboundIn), nKeyedNetGroup(nKeyedNetGroupIn), addrKnown(5000, 0.001), diff --git a/src/net.h b/src/net.h index 5e2fecebb58a..08143fd7c5b9 100644 --- a/src/net.h +++ b/src/net.h @@ -656,8 +656,12 @@ class CNodeStats double dPingTime; double dPingWait; double dMinPing; + // Our address, as reported by the peer std::string addrLocal; + // Address of this peer CAddress addr; + // Bind address of our side of the connection + CAddress addrBind; }; @@ -741,7 +745,10 @@ class CNode std::atomic nLastWarningTime; std::atomic nTimeFirstMessageReceived; std::atomic fFirstMessageIsMNAUTH; + // Address of this peer const CAddress addr; + // Bind address of our side of the connection + const CAddress addrBind; std::atomic nNumWarningsSkipped; std::atomic nVersion; // strSubVer is whatever byte array we read from the wire. However, this field is intended @@ -847,7 +854,7 @@ class CNode // If true, we will send him all quorum related messages, even if he is not a member of our quorums std::atomic qwatch{false}; - CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const std::string &addrNameIn = "", bool fInboundIn = false); + CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); private: @@ -866,6 +873,7 @@ class CNode mutable CCriticalSection cs_addrName; std::string addrName; + // Our address, as reported by the peer CService addrLocal; mutable CCriticalSection cs_addrLocal; public: diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 8dc2748ce6c3..3d31b52d5091 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -77,7 +77,8 @@ UniValue getpeerinfo(const JSONRPCRequest& request) " {\n" " \"id\": n, (numeric) Peer index\n" " \"addr\":\"host:port\", (string) The ip address and port of the peer\n" - " \"addrlocal\":\"ip:port\", (string) local address\n" + " \"addrbind\":\"ip:port\", (string) Bind address of the connection to the peer\n" + " \"addrlocal\":\"ip:port\", (string) Local address as reported by the peer\n" " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n" " \"relaytxes\":true|false, (boolean) Whether peer has asked us to relay transactions to it\n" " \"lastsend\": ttt, (numeric) The time in seconds since epoch (Jan 1 1970 GMT) of the last send\n" @@ -134,6 +135,8 @@ UniValue getpeerinfo(const JSONRPCRequest& request) obj.push_back(Pair("addr", stats.addrName)); if (!(stats.addrLocal.empty())) obj.push_back(Pair("addrlocal", stats.addrLocal)); + if (stats.addrBind.IsValid()) + obj.push_back(Pair("addrbind", stats.addrBind.ToString())); obj.push_back(Pair("services", strprintf("%016x", stats.nServices))); obj.push_back(Pair("relaytxes", stats.fRelayTxes)); obj.push_back(Pair("lastsend", stats.nLastSend)); diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index cb51f1982f84..531b896a2fc5 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) connman->ClearBanned(); CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, "", true); + CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 0, 0, CAddress(), "", true); dummyNode1.SetSendVersion(PROTOCOL_VERSION); GetNodeSignals().InitializeNode(&dummyNode1, *connman); dummyNode1.nVersion = 1; @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(DoS_banning) BOOST_CHECK(!connman->IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned CAddress addr2(ip(0xa0b0c002), NODE_NONE); - CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, "", true); + CNode dummyNode2(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr2, 1, 1, CAddress(), "", true); dummyNode2.SetSendVersion(PROTOCOL_VERSION); GetNodeSignals().InitializeNode(&dummyNode2, *connman); dummyNode2.nVersion = 1; @@ -83,7 +83,7 @@ BOOST_AUTO_TEST_CASE(DoS_banscore) connman->ClearBanned(); gArgs.ForceSetArg("-banscore", "111"); // because 11 is my favorite number CAddress addr1(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, "", true); + CNode dummyNode1(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr1, 3, 1, CAddress(), "", true); dummyNode1.SetSendVersion(PROTOCOL_VERSION); GetNodeSignals().InitializeNode(&dummyNode1, *connman); dummyNode1.nVersion = 1; @@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) SetMockTime(nStartTime); // Overrides future calls to GetTime() CAddress addr(ip(0xa0b0c001), NODE_NONE); - CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, "", true); + CNode dummyNode(id++, NODE_NETWORK, 0, INVALID_SOCKET, addr, 4, 4, CAddress(), "", true); dummyNode.SetSendVersion(PROTOCOL_VERSION); GetNodeSignals().InitializeNode(&dummyNode, *connman); dummyNode.nVersion = 1; diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp index 157b719e1d93..fbb12545d5cd 100644 --- a/src/test/net_tests.cpp +++ b/src/test/net_tests.cpp @@ -175,12 +175,12 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test) bool fInboundIn = false; // Test that fFeeler is false by default. - std::unique_ptr pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, pszDest, fInboundIn)); + std::unique_ptr pnode1(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, fInboundIn)); BOOST_CHECK(pnode1->fInbound == false); BOOST_CHECK(pnode1->fFeeler == false); fInboundIn = true; - std::unique_ptr pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, pszDest, fInboundIn)); + std::unique_ptr pnode2(new CNode(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, fInboundIn)); BOOST_CHECK(pnode2->fInbound == true); BOOST_CHECK(pnode2->fFeeler == false); } diff --git a/test/functional/net.py b/test/functional/net.py index 7d87525b05f0..e9c63b307242 100755 --- a/test/functional/net.py +++ b/test/functional/net.py @@ -29,6 +29,7 @@ def run_test(self): self._test_getnettotals() self._test_getnetworkinginfo() self._test_getaddednodeinfo() + self._test_getpeerinfo() def _test_connection_count(self): # connect_nodes_bi connects each node to the other @@ -88,6 +89,12 @@ def _test_getaddednodeinfo(self): assert_raises_jsonrpc(-24, "Node has not been added", self.nodes[0].getaddednodeinfo, '1.1.1.1') + def _test_getpeerinfo(self): + peer_info = [x.getpeerinfo() for x in self.nodes] + # check both sides of bidirectional connection between nodes + # the address bound to on one side will be the source address for the other node + assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr']) + assert_equal(peer_info[1][0]['addrbind'], peer_info[0][0]['addr']) if __name__ == '__main__': NetTest().main() From 35bafa14bde2dc592c0b86a1b8628ae3ab2529ce Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 5 Jun 2017 16:25:12 +0200 Subject: [PATCH 309/987] Merge #10515: [test] Add test for getchaintxstats cc36b5e [test] Add test for getchaintxstats (Jimmy Song) Tree-SHA512: a992b55f945118ad7410ab8d7ae7d2696e94a2d4a861d633f4501c439364027e2fddd522cb8b5ed3eb621ec4ed0e9fc683e0139aa6c2e2e27c361640f85f1876 --- test/functional/blockchain.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 700c2788f1d7..272801a44818 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -10,6 +10,7 @@ - getbestblockhash - getblockhash - getblockheader + - getchaintxstats - getnetworkhashps - verifychain @@ -35,12 +36,21 @@ def __init__(self): self.num_nodes = 1 def run_test(self): + self._test_getchaintxstats() self._test_gettxoutsetinfo() self._test_getblockheader() self._test_getdifficulty() self._test_getnetworkhashps() self.nodes[0].verifychain(4, 0) + def _test_getchaintxstats(self): + chaintxstats = self.nodes[0].getchaintxstats(1) + # 200 txs plus genesis tx + assert_equal(chaintxstats['txcount'], 201) + # tx rate should be 1 per 10 minutes, or 1/600 + # we have to round because of binary math + assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1)) + def _test_gettxoutsetinfo(self): node = self.nodes[0] res = node.gettxoutsetinfo() From 51525efd66531a1a81fd394061a366de74bc6b01 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 5 Jun 2017 16:38:48 +0200 Subject: [PATCH 310/987] Merge #10403: Fix importmulti failure to return rescan errors 4d2d604 Fix importmulti failure to return rescan errors (Russell Yanofsky) Tree-SHA512: e5e6d6c5a2bb7230e1bcac1903a4b766cd57bf781fade50c6c9cd5713cd3e768db0987cfda9699b57a53d3a0a60951b96dce5283b3d3ec1f954162c439bc932b --- src/wallet/rpcdump.cpp | 21 ++++++++++++++++----- src/wallet/test/wallet_tests.cpp | 28 +++++++++++++--------------- src/wallet/wallet.cpp | 14 +++++--------- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index eb744665648c..7f35bd6fefcb 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1334,13 +1334,13 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) if (fRescan && fRunScan && requests.size()) { CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max(nLowestTimestamp - TIMESTAMP_WINDOW, 0)) : chainActive.Genesis(); - CBlockIndex* scannedRange = nullptr; + CBlockIndex* scanFailed = nullptr; if (pindex) { - scannedRange = pwallet->ScanForWalletTransactions(pindex, true); + scanFailed = pwallet->ScanForWalletTransactions(pindex, true); pwallet->ReacceptWalletTransactions(); } - if (!scannedRange || scannedRange->nHeight > pindex->nHeight) { + if (scanFailed) { std::vector results = response.getValues(); response.clear(); response.setArray(); @@ -1350,12 +1350,23 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) // range, or if the import result already has an error set, let // the result stand unmodified. Otherwise replace the result // with an error message. - if (GetImportTimestamp(request, now) - TIMESTAMP_WINDOW >= scannedRange->GetBlockTimeMax() || results.at(i).exists("error")) { + if (GetImportTimestamp(request, now) - TIMESTAMP_WINDOW > scanFailed->GetBlockTimeMax() || results.at(i).exists("error")) { response.push_back(results.at(i)); } else { UniValue result = UniValue(UniValue::VOBJ); result.pushKV("success", UniValue(false)); - result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, strprintf("Failed to rescan before time %d, transactions may be missing.", scannedRange->GetBlockTimeMax()))); + result.pushKV( + "error", + JSONRPCError( + RPC_MISC_ERROR, + strprintf("Rescan failed for key with creation timestamp %d. There was an error reading a " + "block from time %d, which is after or within %d seconds of key creation, and " + "could contain transactions pertaining to the key. As a result, transactions " + "and coins using this key may not appear in the wallet. This error could be " + "caused by pruning or data corruption (see bitcoind log for details) and could " + "be dealt with by downloading and rescanning the relevant blocks (see -reindex " + "and -rescan options).", + GetImportTimestamp(request, now), scanFailed->GetBlockTimeMax(), TIMESTAMP_WINDOW))); response.push_back(std::move(result)); } ++i; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 140d4e3691e6..9354aec88684 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -364,6 +364,7 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset) BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) { // Cap last block file size, and mine new block in a new block file. + CBlockIndex* const nullBlock = nullptr; CBlockIndex* oldTip = chainActive.Tip(); GetBlockFileInfo(oldTip->GetBlockPos().nFile)->nSize = MAX_BLOCKFILE_SIZE; CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())); @@ -377,7 +378,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) CWallet wallet; LOCK(wallet.cs_wallet); wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); - BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip)); + BOOST_CHECK_EQUAL(nullBlock, wallet.ScanForWalletTransactions(oldTip)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 1000 * COIN); } @@ -391,7 +392,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) CWallet wallet; LOCK(wallet.cs_wallet); wallet.AddKeyPubKey(coinbaseKey, coinbaseKey.GetPubKey()); - BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(oldTip)); + BOOST_CHECK_EQUAL(oldTip, wallet.ScanForWalletTransactions(oldTip)); BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 500 * COIN); } @@ -415,7 +416,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) CKey futureKey; futureKey.MakeNewKey(true); key.pushKV("scriptPubKey", HexStr(GetScriptForRawPubKey(futureKey.GetPubKey()))); - key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW); + key.pushKV("timestamp", newTip->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1); key.pushKV("internal", UniValue(true)); keys.push_back(key); JSONRPCRequest request; @@ -423,20 +424,17 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) request.params.push_back(keys); UniValue response = importmulti(request); - BOOST_CHECK_EQUAL(response.write(), strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Failed to rescan before time %d, transactions may be missing.\"}},{\"success\":true}]", newTip->GetBlockTimeMax())); + BOOST_CHECK_EQUAL(response.write(), + strprintf("[{\"success\":false,\"error\":{\"code\":-1,\"message\":\"Rescan failed for key with creation " + "timestamp %d. There was an error reading a block from time %d, which is after or within %d " + "seconds of key creation, and could contain transactions pertaining to the key. As a result, " + "transactions and coins using this key may not appear in the wallet. This error could be caused " + "by pruning or data corruption (see bitcoind log for details) and could be dealt with by " + "downloading and rescanning the relevant blocks (see -reindex and -rescan " + "options).\"}},{\"success\":true}]", + 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); ::pwalletMain = backup; } - - // Verify ScanForWalletTransactions does not return null when the scan is - // elided due to the nTimeFirstKey optimization. - { - CWallet wallet; - { - LOCK(wallet.cs_wallet); - wallet.UpdateTimeFirstKey(newTip->GetBlockTime() + 7200 + 1); - } - BOOST_CHECK_EQUAL(newTip, wallet.ScanForWalletTransactions(newTip)); - } } // Verify importwallet RPC starts rescan at earliest block with timestamp diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 6c623bb0669d..e56f054a4062 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1824,10 +1824,9 @@ void CWalletTx::GetAmounts(std::list& listReceived, * from or to us. If fUpdate is true, found transactions that already * exist in the wallet will be updated. * - * Returns pointer to the first block in the last contiguous range that was - * successfully scanned or elided (elided if pIndexStart points at a block - * before CWallet::nTimeFirstKey). Returns null if there is no such range, or - * the range doesn't include chainActive.Tip(). + * Returns null if scan was successful. Otherwise, if a complete rescan was not + * possible (due to pruning or corruption), returns pointer to the most recent + * block that could not be scanned. */ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) { @@ -1835,7 +1834,7 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f const CChainParams& chainParams = Params(); CBlockIndex* pindex = pindexStart; - CBlockIndex* ret = pindexStart; + CBlockIndex* ret = nullptr; { LOCK2(cs_main, cs_wallet); fAbortRescan = false; @@ -1863,11 +1862,8 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f for (size_t posInBlock = 0; posInBlock < block.vtx.size(); ++posInBlock) { AddToWalletIfInvolvingMe(block.vtx[posInBlock], pindex, posInBlock, fUpdate); } - if (!ret) { - ret = pindex; - } } else { - ret = nullptr; + ret = pindex; } pindex = chainActive.Next(pindex); } From 175d68ac21c0eae0416a3d90c13d63c394910ced Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 6 Jun 2017 11:26:28 +0200 Subject: [PATCH 311/987] Merge #10426: Replace bytes_serialized with bogosize 8b22af3 Replace bytes_serialized with bogosize (Pieter Wuille) Tree-SHA512: e70a981bbb977329f9e324c45f9a1346ec9aacfbbad5474e608cdd1f852257502bb7db8003fd578260a609e45d1a9cf87ce96df9c4187d92d50f60a209e232ce --- src/rpc/blockchain.cpp | 9 +++++++-- test/functional/blockchain.py | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index fab1fb2ff277..e73015be19cc 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1022,11 +1022,12 @@ struct CCoinsStats uint256 hashBlock; uint64_t nTransactions; uint64_t nTransactionOutputs; + uint64_t nBogoSize; uint256 hashSerialized; uint64_t nDiskSize; CAmount nTotalAmount; - CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nTotalAmount(0) {} + CCoinsStats() : nHeight(0), nTransactions(0), nTransactionOutputs(0), nBogoSize(0), nDiskSize(0), nTotalAmount(0) {} }; static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, const std::map& outputs) @@ -1041,6 +1042,8 @@ static void ApplyStats(CCoinsStats &stats, CHashWriter& ss, const uint256& hash, ss << VARINT(output.second.out.nValue); stats.nTransactionOutputs++; stats.nTotalAmount += output.second.out.nValue; + stats.nBogoSize += 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ + 8 /* amount */ + + 2 /* scriptPubKey len */ + output.second.out.scriptPubKey.size() /* scriptPubKey */; } ss << VARINT(0); } @@ -1145,7 +1148,8 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) " \"bestblock\": \"hex\", (string) the best block hash hex\n" " \"transactions\": n, (numeric) The number of transactions\n" " \"txouts\": n, (numeric) The number of unspent transaction outputs\n" - " \"hash_serialized\": \"hash\", (string) The serialized hash\n" + " \"bogosize\": n, (numeric) A meaningless metric for UTXO set size\n" + " \"hash_serialized_2\": \"hash\", (string) The serialized hash\n" " \"disk_size\": n, (numeric) The estimated size of the chainstate on disk\n" " \"total_amount\": x.xxx (numeric) The total amount\n" "}\n" @@ -1163,6 +1167,7 @@ UniValue gettxoutsetinfo(const JSONRPCRequest& request) ret.push_back(Pair("bestblock", stats.hashBlock.GetHex())); ret.push_back(Pair("transactions", (int64_t)stats.nTransactions)); ret.push_back(Pair("txouts", (int64_t)stats.nTransactionOutputs)); + ret.push_back(Pair("bogosize", (int64_t)stats.nBogoSize)); ret.push_back(Pair("hash_serialized_2", stats.hashSerialized.GetHex())); ret.push_back(Pair("disk_size", stats.nDiskSize)); ret.push_back(Pair("total_amount", ValueFromAmount(stats.nTotalAmount))); diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 272801a44818..c0ebad6912fe 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -59,6 +59,7 @@ def _test_gettxoutsetinfo(self): assert_equal(res['transactions'], 200) assert_equal(res['height'], 200) assert_equal(res['txouts'], 200) + assert_equal(res['bogosize'], 17000), size = res['disk_size'] assert size > 6400 assert size < 64000 @@ -74,6 +75,7 @@ def _test_gettxoutsetinfo(self): assert_equal(res2['total_amount'], Decimal('0')) assert_equal(res2['height'], 0) assert_equal(res2['txouts'], 0) + assert_equal(res2['bogosize'], 0), assert_equal(res2['bestblock'], node.getblockhash(0)) assert_equal(len(res2['hash_serialized_2']), 64) @@ -85,6 +87,7 @@ def _test_gettxoutsetinfo(self): assert_equal(res['transactions'], res3['transactions']) assert_equal(res['height'], res3['height']) assert_equal(res['txouts'], res3['txouts']) + assert_equal(res['bogosize'], res3['bogosize']) assert_equal(res['bestblock'], res3['bestblock']) assert_equal(res['hash_serialized_2'], res3['hash_serialized_2']) From 50652674b5d029d9ebe02c5e75ecf01b67ebe6dd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 9 May 2017 09:29:12 +0200 Subject: [PATCH 312/987] Merge #8855: Use a proper factory for creating chainparams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit c1082a7 Chainparams: Use the factory for pow tests (Jorge Timón) 2351a06 Chainparams: Get rid of CChainParams& Params(std::string) (Jorge Timón) f87f362 Chainparams: Use a regular factory for creating chainparams (Jorge Timón) Tree-SHA512: 359c8a2a1bc9d02db7856d02810240ada28048ac088f878b575597a7255cdb0ffdd1a647085ee67a34c6a7e7ed9e6cfdb61240cf6e75139619b640dbb096072c --- src/bench/checkblock.cpp | 4 +- src/chainparams.cpp | 88 ++++++++++++++++------------------ src/chainparams.h | 22 +++++---- src/chainparamsbase.cpp | 32 ++++--------- src/chainparamsbase.h | 10 +++- src/dash-cli.cpp | 4 +- src/evo/providertx.cpp | 2 +- src/init.cpp | 22 +++++---- src/qt/paymentserver.cpp | 10 ++-- src/test/miner_tests.cpp | 3 +- src/test/pow_tests.cpp | 41 +++++++--------- src/test/subsidy_tests.cpp | 18 +++---- src/test/versionbits_tests.cpp | 6 ++- 13 files changed, 130 insertions(+), 132 deletions(-) diff --git a/src/bench/checkblock.cpp b/src/bench/checkblock.cpp index 45ac54d62a34..823740a1d7d4 100644 --- a/src/bench/checkblock.cpp +++ b/src/bench/checkblock.cpp @@ -38,7 +38,7 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state) char a = '\0'; stream.write(&a, 1); // Prevent compaction - Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus(); + const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); while (state.KeepRunning()) { CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here @@ -46,7 +46,7 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state) assert(stream.Rewind(sizeof(raw_bench::block813851))); CValidationState validationState; - assert(CheckBlock(block, validationState, params, block.GetBlockTime())); + assert(CheckBlock(block, validationState, chainParams->GetConsensus(), block.GetBlockTime())); } } diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 0c1770bc5473..edaead132dcf 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -82,6 +82,32 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward); } + +void CChainParams::UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold) +{ + consensus.vDeployments[d].nStartTime = nStartTime; + consensus.vDeployments[d].nTimeout = nTimeout; + if (nWindowSize != -1) { + consensus.vDeployments[d].nWindowSize = nWindowSize; + } + if (nThreshold != -1) { + consensus.vDeployments[d].nThreshold = nThreshold; + } +} + +void CChainParams::UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight) +{ + consensus.DIP0003Height = nActivationHeight; + consensus.DIP0003EnforcementHeight = nEnforcementHeight; +} + +void CChainParams::UpdateBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock) +{ + consensus.nMasternodePaymentsStartBlock = nMasternodePaymentsStartBlock; + consensus.nBudgetPaymentsStartBlock = nBudgetPaymentsStartBlock; + consensus.nSuperblockStartBlock = nSuperblockStartBlock; +} + static CBlock FindDevNetGenesisBlock(const Consensus::Params& params, const CBlock &prevBlock, const CAmount& reward) { std::string devNetName = GetDevNetName(); @@ -370,7 +396,6 @@ class CMainParams : public CChainParams { }; } }; -static CMainParams mainParams; /** * Testnet (v3) @@ -529,7 +554,6 @@ class CTestNetParams : public CChainParams { } }; -static CTestNetParams testNetParams; /** * Devnet @@ -823,54 +847,26 @@ class CRegTestParams : public CChainParams { consensus.llmqChainLocks = Consensus::LLMQ_5_60; consensus.llmqForInstantSend = Consensus::LLMQ_5_60; } - - void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold) - { - consensus.vDeployments[d].nStartTime = nStartTime; - consensus.vDeployments[d].nTimeout = nTimeout; - if (nWindowSize != -1) { - consensus.vDeployments[d].nWindowSize = nWindowSize; - } - if (nThreshold != -1) { - consensus.vDeployments[d].nThreshold = nThreshold; - } - } - - void UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight) - { - consensus.DIP0003Height = nActivationHeight; - consensus.DIP0003EnforcementHeight = nEnforcementHeight; - } - - void UpdateBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock) - { - consensus.nMasternodePaymentsStartBlock = nMasternodePaymentsStartBlock; - consensus.nBudgetPaymentsStartBlock = nBudgetPaymentsStartBlock; - consensus.nSuperblockStartBlock = nSuperblockStartBlock; - } }; -static CRegTestParams regTestParams; -static CChainParams *pCurrentParams = 0; +static std::unique_ptr globalChainParams; const CChainParams &Params() { - assert(pCurrentParams); - return *pCurrentParams; + assert(globalChainParams); + return *globalChainParams; } -CChainParams& Params(const std::string& chain) +std::unique_ptr CreateChainParams(const std::string& chain) { if (chain == CBaseChainParams::MAIN) - return mainParams; + return std::unique_ptr(new CMainParams()); else if (chain == CBaseChainParams::TESTNET) - return testNetParams; + return std::unique_ptr(new CTestNetParams()); else if (chain == CBaseChainParams::DEVNET) { - assert(devNetParams); - return *devNetParams; + return std::unique_ptr(new CDevNetParams()); } else if (chain == CBaseChainParams::REGTEST) - return regTestParams; - else - throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); + return std::unique_ptr(new CRegTestParams()); + throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); } void SelectParams(const std::string& network) @@ -882,22 +878,22 @@ void SelectParams(const std::string& network) } SelectBaseParams(network); - pCurrentParams = &Params(network); + globalChainParams = CreateChainParams(network); } -void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold) +void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold) { - regTestParams.UpdateBIP9Parameters(d, nStartTime, nTimeout, nWindowSize, nThreshold); + globalChainParams->UpdateBIP9Parameters(d, nStartTime, nTimeout, nWindowSize, nThreshold); } -void UpdateRegtestDIP3Parameters(int nActivationHeight, int nEnforcementHeight) +void UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight) { - regTestParams.UpdateDIP3Parameters(nActivationHeight, nEnforcementHeight); + globalChainParams->UpdateDIP3Parameters(nActivationHeight, nEnforcementHeight); } -void UpdateRegtestBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock) +void UpdateBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock) { - regTestParams.UpdateBudgetParameters(nMasternodePaymentsStartBlock, nBudgetPaymentsStartBlock, nSuperblockStartBlock); + globalChainParams->UpdateBudgetParameters(nMasternodePaymentsStartBlock, nBudgetPaymentsStartBlock, nSuperblockStartBlock); } void UpdateDevnetSubsidyAndDiffParams(int nMinimumDifficultyBlocks, int nHighSubsidyBlocks, int nHighSubsidyFactor) diff --git a/src/chainparams.h b/src/chainparams.h index 12e4448680b6..2a0a2b597190 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -11,6 +11,7 @@ #include "primitives/block.h" #include "protocol.h" +#include #include struct CDNSSeedData { @@ -83,6 +84,9 @@ class CChainParams const std::vector& FixedSeeds() const { return vFixedSeeds; } const CCheckpointData& Checkpoints() const { return checkpointData; } const ChainTxData& TxData() const { return chainTxData; } + void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold); + void UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight); + void UpdateBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock); int PoolMinParticipants() const { return nPoolMinParticipants; } int PoolMaxParticipants() const { return nPoolMaxParticipants; } int FulfilledRequestExpireTime() const { return nFulfilledRequestExpireTime; } @@ -120,15 +124,17 @@ class CChainParams }; /** - * Return the currently selected parameters. This won't change after app - * startup, except for unit tests. + * Creates and returns a std::unique_ptr of the chosen chain. + * @returns a CChainParams* of the chosen chain. + * @throws a std::runtime_error if the chain is not supported. */ -const CChainParams &Params(); +std::unique_ptr CreateChainParams(const std::string& chain); /** - * @returns CChainParams for the given BIP70 chain name. + * Return the currently selected parameters. This won't change after app + * startup, except for unit tests. */ -CChainParams& Params(const std::string& chain); +const CChainParams &Params(); /** * Sets the params returned by Params() to those for the given BIP70 chain name. @@ -139,17 +145,17 @@ void SelectParams(const std::string& chain); /** * Allows modifying the BIP9 regtest parameters. */ -void UpdateRegtestBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold); +void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold); /** * Allows modifying the DIP3 activation and enforcement height */ -void UpdateRegtestDIP3Parameters(int nActivationHeight, int nEnforcementHeight); +void UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight); /** * Allows modifying the budget regtest parameters. */ -void UpdateRegtestBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock); +void UpdateBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock); /** * Allows modifying the subsidy and difficulty devnet parameters. diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 57f1d8deb826..d9080cfdf1cc 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -37,7 +37,6 @@ class CBaseMainParams : public CBaseChainParams nRPCPort = 9998; } }; -static CBaseMainParams mainParams; /** * Testnet (v3) @@ -51,7 +50,6 @@ class CBaseTestNetParams : public CBaseChainParams strDataDir = "testnet3"; } }; -static CBaseTestNetParams testNetParams; /** * Devnet @@ -65,7 +63,6 @@ class CBaseDevNetParams : public CBaseChainParams strDataDir = dataDir; } }; -static CBaseDevNetParams *devNetParams; /* * Regression test @@ -79,43 +76,32 @@ class CBaseRegTestParams : public CBaseChainParams strDataDir = "regtest"; } }; -static CBaseRegTestParams regTestParams; -static CBaseChainParams* pCurrentBaseParams = 0; +static std::unique_ptr globalChainBaseParams; const CBaseChainParams& BaseParams() { - assert(pCurrentBaseParams); - return *pCurrentBaseParams; + assert(globalChainBaseParams); + return *globalChainBaseParams; } -CBaseChainParams& BaseParams(const std::string& chain) +std::unique_ptr CreateBaseChainParams(const std::string& chain) { if (chain == CBaseChainParams::MAIN) - return mainParams; + return std::unique_ptr(new CBaseMainParams()); else if (chain == CBaseChainParams::TESTNET) - return testNetParams; + return std::unique_ptr(new CBaseTestNetParams()); else if (chain == CBaseChainParams::DEVNET) { - assert(devNetParams); - return *devNetParams; + return std::unique_ptr(new CBaseDevNetParams(GetDevNetName())); } else if (chain == CBaseChainParams::REGTEST) - return regTestParams; + return std::unique_ptr(new CBaseRegTestParams()); else throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); } void SelectBaseParams(const std::string& chain) { - if (chain == CBaseChainParams::DEVNET) { - std::string devNetName = GetDevNetName(); - assert(!devNetName.empty()); - - devNetParams = (CBaseDevNetParams*)new uint8_t[sizeof(CBaseDevNetParams)]; - memset(devNetParams, 0, sizeof(CBaseDevNetParams)); - new (devNetParams) CBaseDevNetParams(devNetName); - } - - pCurrentBaseParams = &BaseParams(chain); + globalChainBaseParams = CreateBaseChainParams(chain); } std::string ChainNameFromCommandLine() diff --git a/src/chainparamsbase.h b/src/chainparamsbase.h index 780a35a25519..b2b8c19f18e6 100644 --- a/src/chainparamsbase.h +++ b/src/chainparamsbase.h @@ -5,6 +5,7 @@ #ifndef BITCOIN_CHAINPARAMSBASE_H #define BITCOIN_CHAINPARAMSBASE_H +#include #include #include @@ -31,6 +32,13 @@ class CBaseChainParams std::string strDataDir; }; +/** + * Creates and returns a std::unique_ptr of the chosen chain. + * @returns a CBaseChainParams* of the chosen chain. + * @throws a std::runtime_error if the chain is not supported. + */ +std::unique_ptr CreateBaseChainParams(const std::string& chain); + /** * Append the help messages for the chainparams options to the * parameter string. @@ -43,8 +51,6 @@ void AppendParamsHelpMessages(std::string& strUsage, bool debugHelp=true); */ const CBaseChainParams& BaseParams(); -CBaseChainParams& BaseParams(const std::string& chain); - /** Sets the params returned by Params() to those for the given network. */ void SelectBaseParams(const std::string& chain); diff --git a/src/dash-cli.cpp b/src/dash-cli.cpp index ea45e9ed5717..0e23ef6ad154 100644 --- a/src/dash-cli.cpp +++ b/src/dash-cli.cpp @@ -32,6 +32,8 @@ static const int CONTINUE_EXECUTION=-1; std::string HelpMessageCli() { + const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN); + const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET); std::string strUsage; strUsage += HelpMessageGroup(_("Options:")); strUsage += HelpMessageOpt("-?", _("This help message")); @@ -40,7 +42,7 @@ std::string HelpMessageCli() AppendParamsHelpMessages(strUsage); strUsage += HelpMessageOpt("-named", strprintf(_("Pass named instead of positional arguments (default: %s)"), DEFAULT_NAMED)); strUsage += HelpMessageOpt("-rpcconnect=", strprintf(_("Send commands to node running on (default: %s)"), DEFAULT_RPCCONNECT)); - strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Connect to JSON-RPC on (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort())); + strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Connect to JSON-RPC on (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort())); strUsage += HelpMessageOpt("-rpcwait", _("Wait for RPC server to start")); strUsage += HelpMessageOpt("-rpcuser=", _("Username for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcpassword=", _("Password for JSON-RPC connections")); diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp index 7dc094ce628f..f4cec8262055 100644 --- a/src/evo/providertx.cpp +++ b/src/evo/providertx.cpp @@ -27,7 +27,7 @@ static bool CheckService(const uint256& proTxHash, const ProTx& proTx, CValidati return state.DoS(10, false, REJECT_INVALID, "bad-protx-addr"); } - int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort(); + int mainnetDefaultPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPort(); if (Params().NetworkIDString() == CBaseChainParams::MAIN) { if (proTx.addr.GetPort() != mainnetDefaultPort) { return state.DoS(10, false, REJECT_INVALID, "bad-protx-addr-port"); diff --git a/src/init.cpp b/src/init.cpp index ce49fdd6f3cc..eb89f0046222 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -434,6 +434,10 @@ void OnRPCPreCommand(const CRPCCommand& cmd) std::string HelpMessage(HelpMessageMode mode) { + const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN); + const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET); + const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN); + const auto testnetChainParams = CreateChainParams(CBaseChainParams::TESTNET); const bool showDebug = gArgs.GetBoolArg("-help-debug", false); // When adding new options to the categories, please keep and ensure alphabetical ordering. @@ -445,7 +449,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-blocknotify=", _("Execute command when the best block changes (%s in cmd is replaced by block hash)")); if (showDebug) strUsage += HelpMessageOpt("-blocksonly", strprintf(_("Whether to operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY)); - strUsage +=HelpMessageOpt("-assumevalid=", strprintf(_("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)"), Params(CBaseChainParams::MAIN).GetConsensus().defaultAssumeValid.GetHex(), Params(CBaseChainParams::TESTNET).GetConsensus().defaultAssumeValid.GetHex())); + strUsage +=HelpMessageOpt("-assumevalid=", strprintf(_("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet: %s)"), defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex())); strUsage += HelpMessageOpt("-conf=", strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME)); if (mode == HMM_BITCOIND) { @@ -502,7 +506,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-onlynet=", _("Only connect to nodes in network (ipv4, ipv6 or onion)")); strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG)); strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), DEFAULT_PEERBLOOMFILTERS)); - strUsage += HelpMessageOpt("-port=", strprintf(_("Listen for connections on (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort())); + strUsage += HelpMessageOpt("-port=", strprintf(_("Listen for connections on (default: %u or testnet: %u)"), defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort())); strUsage += HelpMessageOpt("-proxy=", _("Connect through SOCKS5 proxy")); strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE)); strUsage += HelpMessageOpt("-seednode=", _("Connect to a node to retrieve peer addresses, and disconnect")); @@ -547,8 +551,8 @@ std::string HelpMessage(HelpMessageMode mode) { strUsage += HelpMessageOpt("-checkblocks=", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS)); strUsage += HelpMessageOpt("-checklevel=", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), DEFAULT_CHECKLEVEL)); - strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks())); - strUsage += HelpMessageOpt("-checkmempool=", strprintf("Run checks every transactions (default: %u)", Params(CBaseChainParams::MAIN).DefaultConsistencyChecks())); + strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", defaultChainParams->DefaultConsistencyChecks())); + strUsage += HelpMessageOpt("-checkmempool=", strprintf("Run checks every transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks())); strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED)); strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE)); strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE)); @@ -617,7 +621,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageGroup(_("Node relay options:")); if (showDebug) { - strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !Params(CBaseChainParams::TESTNET).RequireStandard())); + strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", defaultChainParams->RequireStandard())); strUsage += HelpMessageOpt("-incrementalrelayfee=", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE))); strUsage += HelpMessageOpt("-dustrelayfee=", strprintf("Fee rate (in %s/kB) used to defined dust, the value of an output such that it will cost about 1/3 of its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE))); } @@ -643,7 +647,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-rpcuser=", _("Username for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcpassword=", _("Password for JSON-RPC connections")); strUsage += HelpMessageOpt("-rpcauth=", _("Username and hashed password for JSON-RPC connections. The field comes in the format: :$. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=/rpcpassword= pair of arguments. This option can be specified multiple times")); - strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Listen for JSON-RPC connections on (default: %u or testnet: %u)"), BaseParams(CBaseChainParams::MAIN).RPCPort(), BaseParams(CBaseChainParams::TESTNET).RPCPort())); + strUsage += HelpMessageOpt("-rpcport=", strprintf(_("Listen for JSON-RPC connections on (default: %u or testnet: %u)"), defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort())); strUsage += HelpMessageOpt("-rpcallowip=", _("Allow JSON-RPC connections from specified source. Valid for are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times")); strUsage += HelpMessageOpt("-rpcthreads=", strprintf(_("Set the number of threads to service RPC calls (default: %d)"), DEFAULT_HTTP_THREADS)); if (showDebug) { @@ -1348,7 +1352,7 @@ bool AppInitParameterInteraction() for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) { - UpdateRegtestBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, nWindowSize, nThreshold); + UpdateBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, nWindowSize, nThreshold); found = true; LogPrintf("Setting BIP9 activation parameters for %s to start=%ld, timeout=%ld, window=%ld, threshold=%ld\n", vDeploymentParams[0], nStartTime, nTimeout, nWindowSize, nThreshold); break; @@ -1378,7 +1382,7 @@ bool AppInitParameterInteraction() if (!ParseInt32(vDIP3Params[1], &nDIP3EnforcementHeight)) { return InitError(strprintf("Invalid nDIP3EnforcementHeight (%s)", vDIP3Params[1])); } - UpdateRegtestDIP3Parameters(nDIP3ActivationHeight, nDIP3EnforcementHeight); + UpdateDIP3Parameters(nDIP3ActivationHeight, nDIP3EnforcementHeight); } if (gArgs.IsArgSet("-budgetparams")) { @@ -1403,7 +1407,7 @@ bool AppInitParameterInteraction() if (!ParseInt32(vBudgetParams[2], &nSuperblockStartBlock)) { return InitError(strprintf("Invalid nSuperblockStartBlock (%s)", vBudgetParams[2])); } - UpdateRegtestBudgetParameters(nMasternodePaymentsStartBlock, nBudgetPaymentsStartBlock, nSuperblockStartBlock); + UpdateBudgetParameters(nMasternodePaymentsStartBlock, nBudgetPaymentsStartBlock, nSuperblockStartBlock); } if (chainparams.NetworkIDString() == CBaseChainParams::DEVNET) { diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 7de53e56fb04..a15f2be9d9d1 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -220,14 +220,16 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[]) if (GUIUtil::parseBitcoinURI(arg, &r) && !r.address.isEmpty()) { CBitcoinAddress address(r.address.toStdString()); + auto tempChainParams = CreateChainParams(CBaseChainParams::MAIN); - if (address.IsValid(Params(CBaseChainParams::MAIN))) + if (address.IsValid(*tempChainParams)) { SelectParams(CBaseChainParams::MAIN); } - else if (address.IsValid(Params(CBaseChainParams::TESTNET))) - { - SelectParams(CBaseChainParams::TESTNET); + else { + tempChainParams = CreateChainParams(CBaseChainParams::TESTNET); + if (address.IsValid(*tempChainParams)) + SelectParams(CBaseChainParams::TESTNET); } } } diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 876667649a06..d145da43f5bd 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -198,7 +198,8 @@ void TestPackageSelection(const CChainParams& chainparams, CScript scriptPubKey, // NOTE: These tests rely on CreateNewBlock doing its own self-validation! BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { - const CChainParams& chainparams = Params(CBaseChainParams::MAIN); + const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); + const CChainParams& chainparams = *chainParams; CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; std::unique_ptr pblocktemplate, pemptyblocktemplate; CMutableTransaction tx,tx2; diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 6bcb272dbaf1..3d34c31d210b 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -16,8 +16,7 @@ BOOST_FIXTURE_TEST_SUITE(pow_tests, BasicTestingSetup) /* Test calculation of next difficulty target with DGW */ BOOST_AUTO_TEST_CASE(get_next_work) { - SelectParams(CBaseChainParams::MAIN); - const Consensus::Params& params = Params().GetConsensus(); + const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); // build the chain of 24 blocks CBlockIndex blockIndexLast; @@ -119,81 +118,75 @@ BOOST_AUTO_TEST_CASE(get_next_work) CBlockHeader blockHeader; blockHeader.nTime = 1408732505; // Block #123457 - BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, params), 0x1b1441de); // Block #123457 has 0x1b1441de + BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, chainParams->GetConsensus()), 0x1b1441de); // Block #123457 has 0x1b1441de // test special rules for slow blocks on devnet/testnet gArgs.SoftSetBoolArg("-devnet", true); - SelectParams(CBaseChainParams::DEVNET); - const Consensus::Params& paramsdev = Params().GetConsensus(); + const auto chainParamsDev = CreateChainParams(CBaseChainParams::DEVNET); // make sure normal rules apply blockHeader.nTime = 1408732505; // Block #123457 - BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, paramsdev), 0x1b1441de); // Block #123457 has 0x1b1441de + BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x1b1441de); // Block #123457 has 0x1b1441de // 10x higher target blockHeader.nTime = 1408733090; // Block #123457 (10m+1sec) - BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, paramsdev), 0x1c00c8f8); // Block #123457 has 0x1c00c8f8 + BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x1c00c8f8); // Block #123457 has 0x1c00c8f8 blockHeader.nTime = 1408733689; // Block #123457 (20m) - BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, paramsdev), 0x1c00c8f8); // Block #123457 has 0x1c00c8f8 + BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x1c00c8f8); // Block #123457 has 0x1c00c8f8 // lowest diff possible blockHeader.nTime = 1408739690; // Block #123457 (2h+1sec) - BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, paramsdev), 0x207fffff); // Block #123457 has 0x207fffff + BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x207fffff); // Block #123457 has 0x207fffff blockHeader.nTime = 1408743289; // Block #123457 (3h) - BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, paramsdev), 0x207fffff); // Block #123457 has 0x207fffff + BOOST_CHECK_EQUAL(GetNextWorkRequired(&blockIndexLast, &blockHeader, chainParamsDev->GetConsensus()), 0x207fffff); // Block #123457 has 0x207fffff } /* Test the constraint on the upper bound for next work */ // BOOST_AUTO_TEST_CASE(get_next_work_pow_limit) // { -// SelectParams(CBaseChainParams::MAIN); -// const Consensus::Params& params = Params().GetConsensus(); +// const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); // int64_t nLastRetargetTime = 1231006505; // Block #0 // CBlockIndex pindexLast; // pindexLast.nHeight = 2015; // pindexLast.nTime = 1233061996; // Block #2015 // pindexLast.nBits = 0x1d00ffff; -// BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00ffff); +// BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00ffff); // } /* Test the constraint on the lower bound for actual time taken */ // BOOST_AUTO_TEST_CASE(get_next_work_lower_limit_actual) // { -// SelectParams(CBaseChainParams::MAIN); -// const Consensus::Params& params = Params().GetConsensus(); +// const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); // int64_t nLastRetargetTime = 1279008237; // Block #66528 // CBlockIndex pindexLast; // pindexLast.nHeight = 68543; // pindexLast.nTime = 1279297671; // Block #68543 // pindexLast.nBits = 0x1c05a3f4; -// BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1c0168fd); +// BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1c0168fd); // } /* Test the constraint on the upper bound for actual time taken */ // BOOST_AUTO_TEST_CASE(get_next_work_upper_limit_actual) // { -// SelectParams(CBaseChainParams::MAIN); -// const Consensus::Params& params = Params().GetConsensus(); +// const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); // int64_t nLastRetargetTime = 1263163443; // NOTE: Not an actual block time // CBlockIndex pindexLast; // pindexLast.nHeight = 46367; // pindexLast.nTime = 1269211443; // Block #46367 // pindexLast.nBits = 0x1c387f6f; -// BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, params), 0x1d00e1fd); +// BOOST_CHECK_EQUAL(CalculateNextWorkRequired(&pindexLast, nLastRetargetTime, chainParams->GetConsensus()), 0x1d00e1fd); // } BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) { - SelectParams(CBaseChainParams::MAIN); - const Consensus::Params& params = Params().GetConsensus(); - + const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); std::vector blocks(10000); for (int i = 0; i < 10000; i++) { blocks[i].pprev = i ? &blocks[i - 1] : NULL; blocks[i].nHeight = i; - blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; + blocks[i].nTime = 1269211443 + i * chainParams->GetConsensus().nPowTargetSpacing; blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */ blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } @@ -203,7 +196,7 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) CBlockIndex *p2 = &blocks[GetRand(10000)]; CBlockIndex *p3 = &blocks[GetRand(10000)]; - int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, params); + int64_t tdiff = GetBlockProofEquivalentTime(*p1, *p2, *p3, chainParams->GetConsensus()); BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime()); } } diff --git a/src/test/subsidy_tests.cpp b/src/test/subsidy_tests.cpp index 51a553242726..5680d5394ffa 100644 --- a/src/test/subsidy_tests.cpp +++ b/src/test/subsidy_tests.cpp @@ -13,7 +13,7 @@ BOOST_FIXTURE_TEST_SUITE(subsidy_tests, TestingSetup) BOOST_AUTO_TEST_CASE(block_subsidy_test) { - const Consensus::Params& consensusParams = Params(CBaseChainParams::MAIN).GetConsensus(); + const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); uint32_t nPrevBits; int32_t nPrevHeight; @@ -22,43 +22,43 @@ BOOST_AUTO_TEST_CASE(block_subsidy_test) // details for block 4249 (subsidy returned will be for block 4250) nPrevBits = 0x1c4a47c4; nPrevHeight = 4249; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, consensusParams, false); + nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 50000000000ULL); // details for block 4501 (subsidy returned will be for block 4502) nPrevBits = 0x1c4a47c4; nPrevHeight = 4501; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, consensusParams, false); + nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 5600000000ULL); // details for block 5464 (subsidy returned will be for block 5465) nPrevBits = 0x1c29ec00; nPrevHeight = 5464; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, consensusParams, false); + nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 2100000000ULL); // details for block 5465 (subsidy returned will be for block 5466) nPrevBits = 0x1c29ec00; nPrevHeight = 5465; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, consensusParams, false); + nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 12200000000ULL); // details for block 17588 (subsidy returned will be for block 17589) nPrevBits = 0x1c08ba34; nPrevHeight = 17588; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, consensusParams, false); + nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 6100000000ULL); // details for block 99999 (subsidy returned will be for block 100000) nPrevBits = 0x1b10cf42; nPrevHeight = 99999; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, consensusParams, false); + nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 500000000ULL); // details for block 210239 (subsidy returned will be for block 210240) nPrevBits = 0x1b11548e; nPrevHeight = 210239; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, consensusParams, false); + nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 500000000ULL); // 1st subsidy reduction happens here @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(block_subsidy_test) // details for block 210240 (subsidy returned will be for block 210241) nPrevBits = 0x1b10d50b; nPrevHeight = 210240; - nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, consensusParams, false); + nSubsidy = GetBlockSubsidy(nPrevBits, nPrevHeight, chainParams->GetConsensus(), false); BOOST_CHECK_EQUAL(nSubsidy, 464285715ULL); } diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 0e38f627f4b7..cce36941d8cd 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -209,7 +209,8 @@ BOOST_AUTO_TEST_CASE(versionbits_test) } // Sanity checks of version bit deployments - const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus(); + const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); + const Consensus::Params &mainnetParams = chainParams->GetConsensus(); for (int i=0; i<(int) Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) { uint32_t bitmask = VersionBitsMask(mainnetParams, (Consensus::DeploymentPos)i); // Make sure that no deployment tries to set an invalid bit. @@ -235,7 +236,8 @@ BOOST_AUTO_TEST_CASE(versionbits_computeblockversion) { // Check that ComputeBlockVersion will set the appropriate bit correctly // on mainnet. - const Consensus::Params &mainnetParams = Params(CBaseChainParams::MAIN).GetConsensus(); + const auto chainParams = CreateChainParams(CBaseChainParams::MAIN); + const Consensus::Params &mainnetParams = chainParams->GetConsensus(); // Use the TESTDUMMY deployment for testing purposes. int64_t bit = mainnetParams.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit; From e740604f608a05367a6349b6c44b985fda25306d Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Sat, 22 Jun 2019 14:34:58 +0200 Subject: [PATCH 313/987] No need for zero initialization of devnet params --- src/chainparams.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index edaead132dcf..7d605c32ea6f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -871,12 +871,6 @@ std::unique_ptr CreateChainParams(const std::string& chain) void SelectParams(const std::string& network) { - if (network == CBaseChainParams::DEVNET) { - devNetParams = (CDevNetParams*)new uint8_t[sizeof(CDevNetParams)]; - memset(devNetParams, 0, sizeof(CDevNetParams)); - new (devNetParams) CDevNetParams(); - } - SelectBaseParams(network); globalChainParams = CreateChainParams(network); } From e7d7ecb6e94c333f714e80230f0788c52555297d Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Sat, 22 Jun 2019 14:44:45 +0200 Subject: [PATCH 314/987] Set a few param values to 0 by default These ones are not necessarey set everytime for all networks. --- src/chainparams.h | 6 +++--- src/consensus/params.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/chainparams.h b/src/chainparams.h index 2a0a2b597190..0da6db3a863b 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -115,9 +115,9 @@ class CChainParams bool fAllowMultiplePorts; CCheckpointData checkpointData; ChainTxData chainTxData; - int nPoolMinParticipants; - int nPoolMaxParticipants; - int nFulfilledRequestExpireTime; + int nPoolMinParticipants{0}; + int nPoolMaxParticipants{0}; + int nFulfilledRequestExpireTime{0}; std::vector vSporkAddresses; int nMinSporkKeys; bool fBIP9CheckMasternodesUpgraded; diff --git a/src/consensus/params.h b/src/consensus/params.h index aed42328e62b..7a589165a5fc 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -35,9 +35,9 @@ struct BIP9Deployment { /** Timeout/expiry MedianTime for the deployment attempt. */ int64_t nTimeout; /** The number of past blocks (including the block under consideration) to be taken into account for locking in a fork. */ - int64_t nWindowSize; + int64_t nWindowSize{0}; /** A number of blocks, in the range of 1..nWindowSize, which must signal for a fork in order to lock it in. */ - int64_t nThreshold; + int64_t nThreshold{0}; }; enum LLMQType : uint8_t From 30ad4b8e8c214e43f6af930ceb5472438e7550cf Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 17 May 2017 09:08:04 +0200 Subject: [PATCH 315/987] Merge #8952: Add query options to listunspent RPC call bc63d0e Add query options to listunspent rpc call (Pedro Branco) Tree-SHA512: 2d296eee8df4e7ac378206ac3003a300e6478502d4b814f1ed1a47614222b01cc35dba871345ced68629860c227aff2c9e4b7f0d4ed0aa7de8b04f26c983580f Signed-off-by: Pasta # Conflicts: # src/rpc/client.cpp # src/wallet/rpcwallet.cpp # src/wallet/wallet.cpp # src/wallet/wallet.h --- src/rpc/client.cpp | 1 + src/wallet/rpcwallet.cpp | 42 +++++++++++++++++++++++++++------ src/wallet/wallet.cpp | 50 ++++++++++++++++++++++++++++++++-------- src/wallet/wallet.h | 2 +- 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c5514b1ec57e..5fb3b662c94e 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -100,6 +100,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listunspent", 1, "maxconf" }, { "listunspent", 2, "addresses" }, { "listunspent", 3, "include_unsafe" }, + { "listunspent", 4, "query_options" }, { "getblock", 1, "verbosity" }, { "getblockheader", 1, "verbose" }, { "getblockheaders", 1, "count" }, diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b08a4abc2df8..cd0d40c1517b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2668,9 +2668,9 @@ UniValue listunspent(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || request.params.size() > 4) + if (request.fHelp || request.params.size() > 5) throw std::runtime_error( - "listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] )\n" + "listunspent ( minconf maxconf [\"addresses\",...] [include_unsafe] [query_options])\n" "\nReturns array of unspent transaction outputs\n" "with between minconf and maxconf (inclusive) confirmations.\n" "Optionally filter to only include txouts paid to specified addresses.\n" @@ -2684,6 +2684,13 @@ UniValue listunspent(const JSONRPCRequest& request) " ]\n" "4. include_unsafe (bool, optional, default=true) Include outputs that are not safe to spend\n" " See description of \"safe\" attribute below.\n" + "5. query_options (json, optional) JSON with query options\n" + " {\n" + " \"minimumAmount\" (numeric or string, default=0) Minimum value of each UTXO in " + CURRENCY_UNIT + "\n" + " \"maximumAmount\" (numeric or string, default=unlimited) Maximum value of each UTXO in " + CURRENCY_UNIT + "\n" + " \"maximumCount\" (numeric or string, default=unlimited) Maximum number of UTXOs\n" + " \"minimumSumAmount\" (numeric or string, default=unlimited) Minimum sum value of all UTXOs in " + CURRENCY_UNIT + "\n" + " }\n" "\nResult\n" "[ (array of json object)\n" " {\n" @@ -2709,6 +2716,8 @@ UniValue listunspent(const JSONRPCRequest& request) + HelpExampleCli("listunspent", "") + HelpExampleCli("listunspent", "6 9999999 \"[\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\\\",\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcg\\\"]\"") + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\\\",\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcg\\\"]\"") + + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'") + + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ") ); int nMinDepth = 1; @@ -2744,15 +2753,34 @@ UniValue listunspent(const JSONRPCRequest& request) include_unsafe = request.params[3].get_bool(); } + CAmount nMinimumAmount = 0; + CAmount nMaximumAmount = MAX_MONEY; + CAmount nMinimumSumAmount = MAX_MONEY; + uint64_t nMaximumCount = 0; + + if (request.params.size() > 4) { + const UniValue& options = request.params[4].get_obj(); + + if (options.exists("minimumAmount")) + nMinimumAmount = AmountFromValue(options["minimumAmount"]); + + if (options.exists("maximumAmount")) + nMaximumAmount = AmountFromValue(options["maximumAmount"]); + + if (options.exists("minimumSumAmount")) + nMinimumSumAmount = AmountFromValue(options["minimumSumAmount"]); + + if (options.exists("maximumCount")) + nMaximumCount = options["maximumCount"].get_int64(); + } + UniValue results(UniValue::VARR); std::vector vecOutputs; assert(pwallet != NULL); LOCK2(cs_main, pwallet->cs_wallet); - pwallet->AvailableCoins(vecOutputs, !include_unsafe, NULL, true); - BOOST_FOREACH(const COutput& out, vecOutputs) { - if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) - continue; + pwallet->AvailableCoins(vecOutputs, !include_unsafe, NULL, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth); + BOOST_FOREACH(const COutput& out, vecOutputs) { CTxDestination address; const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey; bool fValidAddress = ExtractDestination(scriptPubKey, address); @@ -3024,7 +3052,7 @@ static const CRPCCommand commands[] = { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","addlocked","include_empty","include_watchonly"} }, { "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} }, { "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} }, - { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe"} }, + { "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe","query_options"} }, { "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} }, { "wallet", "move", &movecmd, false, {"fromaccount","toaccount","amount","minconf","comment"} }, { "wallet", "sendfrom", &sendfrom, false, {"fromaccount","toaddress","amount","minconf","addlocked","comment","comment_to"} }, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e56f054a4062..21eeb7071b76 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2540,7 +2540,7 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, cons return balance; } -void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlySafe, const CCoinControl *coinControl, bool fIncludeZeroValue, AvailableCoinsType nCoinType, bool fUseInstantSend) const +void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t &nMaximumCount, const int &nMinDepth, const int &nMaxDepth, AvailableCoinsType nCoinType, bool fUseInstantSend) const { vCoins.clear(); @@ -2548,6 +2548,8 @@ void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlySafe, const LOCK2(cs_main, cs_wallet); int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired; + CAmount nTotal = 0; + for (std::map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const uint256& wtxid = it->first; @@ -2575,6 +2577,9 @@ void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlySafe, const continue; } + if (nDepth < nMinDepth || nDepth > nMaxDepth) + continue; + for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) { bool found = false; if(nCoinType == ONLY_DENOMINATED) { @@ -2591,15 +2596,42 @@ void CWallet::AvailableCoins(std::vector& vCoins, bool fOnlySafe, const } if(!found) continue; + if (pcoin->tx->vout[i].nValue < nMinimumAmount || pcoin->tx->vout[i].nValue > nMaximumAmount) + continue; + + if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint((*it).first, i))) + continue; + + if (IsLockedCoin((*it).first, i) || nCoinType == ONLY_1000) + continue; + + if (IsSpent(wtxid, i)) + continue; + isminetype mine = IsMine(pcoin->tx->vout[i]); - if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO && - (!IsLockedCoin((*it).first, i) || nCoinType == ONLY_1000) && - (pcoin->tx->vout[i].nValue > 0 || fIncludeZeroValue) && - (!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected(COutPoint((*it).first, i)))) - vCoins.push_back(COutput(pcoin, i, nDepth, - ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || - (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO), - (mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO, safeTx)); + + if (mine == ISMINE_NO) { + continue; + } + + bool fSpendableIn = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO); + bool fSolvableIn = (mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO; + + vCoins.push_back(COutput(pcoin, i, nDepth, fSpendableIn, fSolvableIn, safeTx)); + + // Checks the sum amount of all UTXO's. + if (nMinimumSumAmount != MAX_MONEY) { + nTotal += pcoin->tx->vout[i].nValue; + + if (nTotal >= nMinimumSumAmount) { + return; + } + } + + // Checks the maximum number of UTXO's. + if (nMaximumCount > 0 && vCoins.size() >= nMaximumCount) { + return; + } } } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b8e0b49f1558..682785907fda 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -885,7 +885,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /** * populate vCoins with vector of available COutputs. */ - void AvailableCoins(std::vector& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = false) const; + void AvailableCoins(std::vector& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 9999999, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = false) const; /** * Shuffle and select coins until nTargetValue is reached while avoiding From 535d7d6a8469698420357eab31b3106bd806765c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 23 May 2017 13:58:35 -0700 Subject: [PATCH 316/987] Merge #10347: Use range-based for loops (C++11) when looping over vector elements 211adc0 Use range-based for loops (C++11) when looping over vector elements (practicalswift) Tree-SHA512: 0e007f20dcef99d3c7a1036265e00f689d69f42e02fd82dd8389f45b52d31947e5f9388de2610d3d9bd9f554915ce0d35ebce561e5ae3a9013956d0ee4937145 --- src/net_processing.cpp | 8 +++----- src/policy/fees.cpp | 4 ++-- src/script/interpreter.cpp | 12 ++++++------ src/wallet/wallet.cpp | 16 ++++++++-------- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 2fadd8abad13..49083d709cec 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -815,8 +815,8 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr& pb const CTransaction& tx = *ptx; // Which orphan pool entries must we evict? - for (size_t j = 0; j < tx.vin.size(); j++) { - auto itByPrev = mapOrphanTransactionsByPrev.find(tx.vin[j].prevout); + for (const auto& txin : tx.vin) { + auto itByPrev = mapOrphanTransactionsByPrev.find(txin.prevout); if (itByPrev == mapOrphanTransactionsByPrev.end()) continue; for (auto mi = itByPrev->second.begin(); mi != itByPrev->second.end(); ++mi) { const CTransaction& orphanTx = *(*mi)->second.tx; @@ -1815,10 +1815,8 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); - for (unsigned int nInv = 0; nInv < vInv.size(); nInv++) + for (CInv &inv : vInv) { - const CInv &inv = vInv[nInv]; - if(!inv.IsKnownType()) { LogPrint(BCLog::NET, "got inv of unknown type %d: %s peer=%d\n", inv.type, inv.hash.ToString(), pfrom->GetId()); continue; diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 0b1759a5bbd2..a0c37a70d6fa 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -506,8 +506,8 @@ void CBlockPolicyEstimator::processBlock(unsigned int nBlockHeight, unsigned int countedTxs = 0; // Repopulate the current block states - for (unsigned int i = 0; i < entries.size(); i++) { - if (processBlockTx(nBlockHeight, entries[i])) + for (const auto& entry : entries) { + if (processBlockTx(nBlockHeight, entry)) countedTxs++; } diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 8b06192aaedd..a915776aa908 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -1119,24 +1119,24 @@ class CTransactionSignatureSerializer { uint256 GetPrevoutHash(const CTransaction& txTo) { CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vin.size(); n++) { - ss << txTo.vin[n].prevout; + for (const auto& txin : txTo.vin) { + ss << txin.prevout; } return ss.GetHash(); } uint256 GetSequenceHash(const CTransaction& txTo) { CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vin.size(); n++) { - ss << txTo.vin[n].nSequence; + for (const auto& txin : txTo.vin) { + ss << txin.nSequence; } return ss.GetHash(); } uint256 GetOutputsHash(const CTransaction& txTo) { CHashWriter ss(SER_GETHASH, 0); - for (unsigned int n = 0; n < txTo.vout.size(); n++) { - ss << txTo.vout[n]; + for (const auto& txout : txTo.vout) { + ss << txout; } return ss.GetHash(); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 21eeb7071b76..60b7139e2f02 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2233,8 +2233,8 @@ bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const { CMutableTransaction tx1 = *this->tx; CMutableTransaction tx2 = *_tx.tx; - for (unsigned int i = 0; i < tx1.vin.size(); i++) tx1.vin[i].scriptSig = CScript(); - for (unsigned int i = 0; i < tx2.vin.size(); i++) tx2.vin[i].scriptSig = CScript(); + for (auto& txin : tx1.vin) txin.scriptSig = CScript(); + for (auto& txin : tx2.vin) txin.scriptSig = CScript(); return CTransaction(tx1) == CTransaction(tx2); } @@ -2809,10 +2809,10 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin if (nTotalLower == nTargetValue) { - for (unsigned int i = 0; i < vValue.size(); ++i) + for (const auto& input : vValue) { - setCoinsRet.insert(vValue[i]); - nValueRet += vValue[i].txout.nValue; + setCoinsRet.insert(input); + nValueRet += input.txout.nValue; } return true; } @@ -4377,11 +4377,11 @@ std::set< std::set > CWallet::GetAddressGroupings() } // group lone addrs by themselves - for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) - if (IsMine(pcoin->tx->vout[i])) + for (const auto& txout : pcoin->tx->vout) + if (IsMine(txout)) { CTxDestination address; - if(!ExtractDestination(pcoin->tx->vout[i].scriptPubKey, address)) + if(!ExtractDestination(txout.scriptPubKey, address)) continue; grouping.insert(address); groupings.insert(grouping); From 39cfd61c070717c373cca23fd7d276c6c141af6d Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 9 May 2017 09:11:09 +0200 Subject: [PATCH 317/987] Merge #9279: Consensus: Move CFeeRate out of libconsensus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 381a46e Consensus: Policy: MOVEONLY: Move CFeeRate out of the consensus module (Jorge Timón) 330bb5a Consensus: Minimal way to move dust out of consensus (Jorge Timón) Tree-SHA512: 19a2ea8169afd5a9d3f940d8974e34cfaead153e3ff3068ac82fccdb8694d19d9b45938904ec9e8cd095bd5ca3a0080364da29372f6aaf56b11a6c2ccd6c7a4d --- src/Makefile.am | 3 +- src/amount.h | 45 +-------------------- src/init.cpp | 1 + src/miner.cpp | 1 + src/net.h | 1 + src/{amount.cpp => policy/feerate.cpp} | 2 +- src/policy/feerate.h | 54 ++++++++++++++++++++++++++ src/policy/fees.h | 1 + src/policy/policy.cpp | 23 ++++++++++- src/policy/policy.h | 6 +++ src/primitives/transaction.h | 21 ---------- src/qt/coincontroldialog.cpp | 7 ++-- src/qt/guiutil.cpp | 2 +- src/qt/paymentserver.cpp | 2 +- src/rpc/blockchain.cpp | 1 + src/test/amount_tests.cpp | 1 + src/txmempool.h | 1 + src/validation.h | 1 + src/wallet/coincontrol.h | 1 + src/wallet/rpcwallet.cpp | 1 + src/wallet/wallet.cpp | 10 ++--- src/wallet/wallet.h | 1 + 22 files changed, 107 insertions(+), 79 deletions(-) rename src/{amount.cpp => policy/feerate.cpp} (98%) create mode 100644 src/policy/feerate.h diff --git a/src/Makefile.am b/src/Makefile.am index c3b2d83067b5..0d21098d7fc8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -193,6 +193,7 @@ BITCOIN_CORE_H = \ netfulfilledman.h \ netmessagemaker.h \ noui.h \ + policy/feerate.h \ policy/fees.h \ policy/policy.h \ pow.h \ @@ -456,7 +457,6 @@ libdash_consensus_a_SOURCES = \ libdash_common_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) libdash_common_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libdash_common_a_SOURCES = \ - amount.cpp \ base58.cpp \ bip39.cpp \ chainparams.cpp \ @@ -469,6 +469,7 @@ libdash_common_a_SOURCES = \ keystore.cpp \ netaddress.cpp \ netbase.cpp \ + policy/feerate.cpp \ protocol.cpp \ saltedhasher.cpp \ scheduler.cpp \ diff --git a/src/amount.h b/src/amount.h index ba0c86040f18..3cad29d4e5b6 100644 --- a/src/amount.h +++ b/src/amount.h @@ -6,10 +6,7 @@ #ifndef BITCOIN_AMOUNT_H #define BITCOIN_AMOUNT_H -#include "serialize.h" - -#include -#include +#include /** Amount in satoshis (Can be negative) */ typedef int64_t CAmount; @@ -17,8 +14,6 @@ typedef int64_t CAmount; static const CAmount COIN = 100000000; static const CAmount CENT = 1000000; -extern const std::string CURRENCY_UNIT; - /** No amount larger than this (in satoshi) is valid. * * Note that this constant is *not* the total money supply, which in Bitcoin @@ -31,42 +26,4 @@ extern const std::string CURRENCY_UNIT; static const CAmount MAX_MONEY = 21000000 * COIN; inline bool MoneyRange(const CAmount& nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } -/** - * Fee rate in satoshis per kilobyte: CAmount / kB - */ -class CFeeRate -{ -private: - CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes -public: - /** Fee rate of 0 satoshis per kB */ - CFeeRate() : nSatoshisPerK(0) { } - explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } - /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/ - CFeeRate(const CAmount& nFeePaid, size_t nBytes); - CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } - /** - * Return the fee in satoshis for the given size in bytes. - */ - CAmount GetFee(size_t nBytes) const; - /** - * Return the fee in satoshis for a size of 1000 bytes - */ - CAmount GetFeePerK() const { return GetFee(1000); } - friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; } - friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; } - friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; } - friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; } - friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } - CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; } - std::string ToString() const; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(nSatoshisPerK); - } -}; - #endif // BITCOIN_AMOUNT_H diff --git a/src/init.cpp b/src/init.cpp index eb89f0046222..d19ecc836ee3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -27,6 +27,7 @@ #include "netbase.h" #include "net.h" #include "net_processing.h" +#include "policy/feerate.h" #include "policy/fees.h" #include "policy/policy.h" #include "rpc/server.h" diff --git a/src/miner.cpp b/src/miner.cpp index 0b4f37b34c5b..79218bc6221f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -16,6 +16,7 @@ #include "hash.h" #include "validation.h" #include "net.h" +#include "policy/feerate.h" #include "policy/policy.h" #include "pow.h" #include "primitives/transaction.h" diff --git a/src/net.h b/src/net.h index 08143fd7c5b9..6d648d5bd8b1 100644 --- a/src/net.h +++ b/src/net.h @@ -14,6 +14,7 @@ #include "hash.h" #include "limitedmap.h" #include "netaddress.h" +#include "policy/feerate.h" #include "protocol.h" #include "random.h" #include "saltedhasher.h" diff --git a/src/amount.cpp b/src/policy/feerate.cpp similarity index 98% rename from src/amount.cpp rename to src/policy/feerate.cpp index 4d0c19599b06..e203cb5e7540 100644 --- a/src/amount.cpp +++ b/src/policy/feerate.cpp @@ -3,7 +3,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "amount.h" +#include "feerate.h" #include "tinyformat.h" diff --git a/src/policy/feerate.h b/src/policy/feerate.h new file mode 100644 index 000000000000..e82268b095a3 --- /dev/null +++ b/src/policy/feerate.h @@ -0,0 +1,54 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2015 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_POLICY_FEERATE_H +#define BITCOIN_POLICY_FEERATE_H + +#include "amount.h" +#include "serialize.h" + +#include + +extern const std::string CURRENCY_UNIT; + +/** + * Fee rate in satoshis per kilobyte: CAmount / kB + */ +class CFeeRate +{ +private: + CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes +public: + /** Fee rate of 0 satoshis per kB */ + CFeeRate() : nSatoshisPerK(0) { } + explicit CFeeRate(const CAmount& _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) { } + /** Constructor for a fee rate in satoshis per kB. The size in bytes must not exceed (2^63 - 1)*/ + CFeeRate(const CAmount& nFeePaid, size_t nBytes); + CFeeRate(const CFeeRate& other) { nSatoshisPerK = other.nSatoshisPerK; } + /** + * Return the fee in satoshis for the given size in bytes. + */ + CAmount GetFee(size_t nBytes) const; + /** + * Return the fee in satoshis for a size of 1000 bytes + */ + CAmount GetFeePerK() const { return GetFee(1000); } + friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; } + friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; } + friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; } + friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; } + friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; } + CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; } + std::string ToString() const; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { + READWRITE(nSatoshisPerK); + } +}; + +#endif // BITCOIN_POLICY_FEERATE_H diff --git a/src/policy/fees.h b/src/policy/fees.h index f59f35a273e1..ce087c238e3e 100644 --- a/src/policy/fees.h +++ b/src/policy/fees.h @@ -6,6 +6,7 @@ #define BITCOIN_POLICYESTIMATOR_H #include "amount.h" +#include "feerate.h" #include "uint256.h" #include "random.h" #include "sync.h" diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 53347b5ff27f..9832697475f6 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -15,6 +15,27 @@ #include +CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee) +{ + // "Dust" is defined in terms of CTransaction::minRelayTxFee, which has units duffs-per-kilobyte. + // If you'd pay more than 1/3 in fees to spend something, then we consider it dust. + // A typical spendable txout is 34 bytes big, and will need a CTxIn of at least 148 bytes to spend + // i.e. total is 148 + 34 = 182 bytes. Default -minrelaytxfee is 1000 duffs per kB + // and that means that fee per spendable txout is 182 * 1000 / 1000 = 182 duffs. + // So dust is a spendable txout less than 546 * minRelayTxFee / 1000 (in duffs) + // i.e. 182 * 3 = 546 duffs with default -minrelaytxfee = minRelayTxFee = 1000 duffs per kB. + if (txout.scriptPubKey.IsUnspendable()) + return 0; + + size_t nSize = GetSerializeSize(txout, SER_DISK, 0)+148u; + return 3 * dustRelayFee.GetFee(nSize); +} + +bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee) +{ + return (txout.nValue < GetDustThreshold(txout, dustRelayFee)); +} + /** * Check transaction inputs to mitigate two * potential denial-of-service attacks: @@ -103,7 +124,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) { reason = "bare-multisig"; return false; - } else if (txout.IsDust(dustRelayFee)) { + } else if (IsDust(txout, ::dustRelayFee)) { reason = "dust"; return false; } diff --git a/src/policy/policy.h b/src/policy/policy.h index bb515f1c6862..2312d0fe54e8 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -7,12 +7,14 @@ #define BITCOIN_POLICY_POLICY_H #include "consensus/consensus.h" +#include "feerate.h" #include "script/interpreter.h" #include "script/standard.h" #include class CCoinsViewCache; +class CTxOut; /** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 2000000; @@ -58,6 +60,10 @@ static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_ static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST; +CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee); + +bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee); + bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); /** * Check for standard transaction types diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index 832391556947..bdcd5d5dc304 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -175,27 +175,6 @@ class CTxOut return (nValue == -1); } - CAmount GetDustThreshold(const CFeeRate &minRelayTxFee) const - { - // "Dust" is defined in terms of CTransaction::minRelayTxFee, which has units duffs-per-kilobyte. - // If you'd pay more than 1/3 in fees to spend something, then we consider it dust. - // A typical spendable txout is 34 bytes big, and will need a CTxIn of at least 148 bytes to spend - // i.e. total is 148 + 34 = 182 bytes. Default -minrelaytxfee is 1000 duffs per kB - // and that means that fee per spendable txout is 182 * 1000 / 1000 = 182 duffs. - // So dust is a spendable txout less than 546 * minRelayTxFee / 1000 (in duffs) - // i.e. 182 * 3 = 546 duffs with default -minrelaytxfee = minRelayTxFee = 1000 duffs per kB. - if (scriptPubKey.IsUnspendable()) - return 0; - - size_t nSize = GetSerializeSize(*this, SER_DISK, 0)+148u; - return 3*minRelayTxFee.GetFee(nSize); - } - - bool IsDust(const CFeeRate &minRelayTxFee) const - { - return (nValue < GetDustThreshold(minRelayTxFee)); - } - friend bool operator==(const CTxOut& a, const CTxOut& b) { return (a.nValue == b.nValue && diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 87895c644323..9cdfaddf0912 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -489,8 +489,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) { CTxOut txout(amount, (CScript)std::vector(24, 0)); txDummy.vout.push_back(txout); - if (txout.IsDust(dustRelayFee)) - fDust = true; + fDust |= IsDust(txout, ::dustRelayFee); } } @@ -578,10 +577,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) if (nChange > 0 && nChange < MIN_CHANGE) { CTxOut txout(nChange, (CScript)std::vector(24, 0)); - if (txout.IsDust(dustRelayFee)) + if (IsDust(txout, ::dustRelayFee)) { if (CoinControlDialog::fSubtractFeeFromAmount) // dust-change will be raised until no dust - nChange = txout.GetDustThreshold(dustRelayFee); + nChange = GetDustThreshold(txout, ::dustRelayFee); else { nPayFee += nChange; diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 5e5cc6e13dbe..9fca533cf17b 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -267,7 +267,7 @@ bool isDust(const QString& address, const CAmount& amount) CTxDestination dest = CBitcoinAddress(address.toStdString()).Get(); CScript script = GetScriptForDestination(dest); CTxOut txOut(amount, script); - return txOut.IsDust(dustRelayFee); + return IsDust(txOut, ::dustRelayFee); } QString HtmlEscape(const QString& str, bool fMultiLine) diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index a15f2be9d9d1..22eff5dcfe5f 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -583,7 +583,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen // Extract and check amounts CTxOut txOut(sendingTo.second, sendingTo.first); - if (txOut.IsDust(dustRelayFee)) { + if (IsDust(txOut, ::dustRelayFee)) { Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)), CClientUIInterface::MSG_ERROR); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e73015be19cc..d4aa60021127 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -16,6 +16,7 @@ #include "instantsend.h" #include "validation.h" #include "core_io.h" +#include "policy/feerate.h" #include "policy/policy.h" #include "primitives/transaction.h" #include "rpc/server.h" diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 4fb1d276b4ee..4f1e8e74fc9b 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -3,6 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "amount.h" +#include "policy/feerate.h" #include "test/test_dash.h" #include diff --git a/src/txmempool.h b/src/txmempool.h index 6605c0e084f5..bb37c606cd4a 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -18,6 +18,7 @@ #include "amount.h" #include "coins.h" #include "indirectmap.h" +#include "policy/feerate.h" #include "primitives/transaction.h" #include "sync.h" #include "random.h" diff --git a/src/validation.h b/src/validation.h index ba9a55e6ff19..0875fdc59fe4 100644 --- a/src/validation.h +++ b/src/validation.h @@ -15,6 +15,7 @@ #include "coins.h" #include "fs.h" #include "protocol.h" // For CMessageHeader::MessageStartChars +#include "policy/feerate.h" #include "script/script_error.h" #include "sync.h" #include "versionbits.h" diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index 1946b601b188..2c4c6e710767 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -5,6 +5,7 @@ #ifndef BITCOIN_WALLET_COINCONTROL_H #define BITCOIN_WALLET_COINCONTROL_H +#include "policy/feerate.h" #include "primitives/transaction.h" /** Coin Control Features. */ diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index cd0d40c1517b..fca557fc7778 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -13,6 +13,7 @@ #include "wallet/coincontrol.h" #include "instantsend.h" #include "net.h" +#include "policy/feerate.h" #include "policy/fees.h" #include "rpc/server.h" #include "timedata.h" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 60b7139e2f02..5143a199db54 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3509,7 +3509,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT } } - if (txout.IsDust(dustRelayFee)) + if (IsDust(txout, ::dustRelayFee)) { if (recipient.fSubtractFeeFromAmount && nFeeRet > 0) { @@ -3596,16 +3596,16 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // We do not move dust-change to fees, because the sender would end up paying more than requested. // This would be against the purpose of the all-inclusive feature. // So instead we raise the change and deduct from the recipient. - if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(dustRelayFee)) + if (nSubtractFeeFromAmount > 0 && IsDust(newTxOut, ::dustRelayFee)) { - CAmount nDust = newTxOut.GetDustThreshold(dustRelayFee) - newTxOut.nValue; + CAmount nDust = GetDustThreshold(newTxOut, ::dustRelayFee) - newTxOut.nValue; newTxOut.nValue += nDust; // raise change until no more dust for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient { if (vecSend[i].fSubtractFeeFromAmount) { txNew.vout[i].nValue -= nDust; - if (txNew.vout[i].IsDust(dustRelayFee)) + if (IsDust(txNew.vout[i], ::dustRelayFee)) { strFailReason = _("The transaction amount is too small to send after the fee has been deducted"); return false; @@ -3617,7 +3617,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // Never create dust outputs; if we would, just // add the dust to the fee. - if (newTxOut.IsDust(dustRelayFee)) + if (IsDust(newTxOut, ::dustRelayFee)) { nChangePosInOut = -1; nFeeRet += nChange; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 682785907fda..0dc655672a80 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -9,6 +9,7 @@ #include "amount.h" #include "base58.h" +#include "policy/feerate.h" #include "streams.h" #include "tinyformat.h" #include "ui_interface.h" From b75e1cebd38c28bd5e7ef77397ab29c696b1b0c2 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 27 Jun 2019 23:24:43 +0300 Subject: [PATCH 318/987] Decouple lite mode and client-side PrivateSend (#2893) * Decouple lite mode and client-side PrivateSend `-enableprivatesend`: 1. off by default in lite mode but can be overridden 2. does not start mixing, use `-privatesendautostart` (default is off) or `privatesend` rpc instead * Disable PS when there is no wallet, do not auto-start mixing when wallet is locked * Check for `!fEnablePrivateSend` and `!fPrivateSendRunning` instead of `!pwalletMain` in ps client code * Add meaningful `privatesend` rpc error messages for various cases when mmixing is disabled --- src/dsnotificationinterface.cpp | 9 +++-- src/init.cpp | 42 +++++++++++++------- src/masternode/masternode-utils.cpp | 2 - src/privatesend/privatesend-client.cpp | 54 +++++++++----------------- src/privatesend/privatesend-client.h | 3 ++ src/privatesend/privatesend.cpp | 2 +- src/qt/overviewpage.cpp | 25 ++++++------ src/qt/sendcoinsdialog.cpp | 26 +++++++------ src/rpc/masternode.cpp | 18 ++++++++- src/rpc/misc.cpp | 3 +- src/wallet/rpcwallet.cpp | 6 +-- src/wallet/wallet.cpp | 12 +++--- 12 files changed, 108 insertions(+), 94 deletions(-) diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 8f2cb81f235a..6113f5976ecc 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -56,16 +56,17 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con if (fInitialDownload) return; + CPrivateSend::UpdatedBlockTip(pindexNew); +#ifdef ENABLE_WALLET + privateSendClient.UpdatedBlockTip(pindexNew); +#endif // ENABLE_WALLET + if (fLiteMode) return; llmq::quorumInstantSendManager->UpdatedBlockTip(pindexNew); llmq::chainLocksHandler->UpdatedBlockTip(pindexNew); - CPrivateSend::UpdatedBlockTip(pindexNew); -#ifdef ENABLE_WALLET - privateSendClient.UpdatedBlockTip(pindexNew); -#endif // ENABLE_WALLET instantsend.UpdatedBlockTip(pindexNew); governance.UpdatedBlockTip(pindexNew, connman); llmq::quorumManager->UpdatedBlockTip(pindexNew, fInitialDownload); diff --git a/src/init.cpp b/src/init.cpp index ce49fdd6f3cc..6650a71ced9a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -242,9 +242,9 @@ void PrepareShutdown() bool fRPCInWarmup = RPCIsInWarmup(&statusmessage); #ifdef ENABLE_WALLET - if (!fLiteMode && !fRPCInWarmup) { + if (privateSendClient.fEnablePrivateSend && !fRPCInWarmup) { // Stop PrivateSend, release keys - privateSendClient.fEnablePrivateSend = false; + privateSendClient.fPrivateSendRunning = false; privateSendClient.ResetPool(); } if (pwalletMain) @@ -600,7 +600,8 @@ std::string HelpMessage(HelpMessageMode mode) #ifdef ENABLE_WALLET strUsage += HelpMessageGroup(_("PrivateSend options:")); - strUsage += HelpMessageOpt("-enableprivatesend", strprintf(_("Enable use of automated PrivateSend for funds stored in this wallet (0-1, default: %u)"), 0)); + strUsage += HelpMessageOpt("-enableprivatesend", strprintf(_("Enable use of PrivateSend for funds stored in this wallet (0-1, default: %u)"), 0)); + strUsage += HelpMessageOpt("-privatesendautostart", strprintf(_("Start PrivateSend automatically (0-1, default: %u)"), DEFAULT_PRIVATESEND_AUTOSTART)); strUsage += HelpMessageOpt("-privatesendmultisession", strprintf(_("Enable multiple PrivateSend mixing sessions per block, experimental (0-1, default: %u)"), DEFAULT_PRIVATESEND_MULTISESSION)); strUsage += HelpMessageOpt("-privatesendsessions=", strprintf(_("Use N separate masternodes in parallel to mix funds (%u-%u, default: %u)"), MIN_PRIVATESEND_SESSIONS, MAX_PRIVATESEND_SESSIONS, DEFAULT_PRIVATESEND_SESSIONS)); strUsage += HelpMessageOpt("-privatesendrounds=", strprintf(_("Use N separate masternodes for each denominated input to mix funds (%u-%u, default: %u)"), MIN_PRIVATESEND_ROUNDS, MAX_PRIVATESEND_ROUNDS, DEFAULT_PRIVATESEND_ROUNDS)); @@ -970,6 +971,8 @@ void InitParameterInteraction() if (nLiqProvTmp > 0) { gArgs.ForceSetArg("-enableprivatesend", "1"); LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -enableprivatesend=1\n", __func__, nLiqProvTmp); + gArgs.ForceSetArg("-privatesendautostart", "1"); + LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendautostart=1\n", __func__, nLiqProvTmp); gArgs.ForceSetArg("-privatesendsessions", itostr(MIN_PRIVATESEND_SESSIONS)); LogPrintf("%s: parameter interaction: -liquidityprovider=%d -> setting -privatesendsessions=%d\n", __func__, nLiqProvTmp, itostr(std::numeric_limits::max())); gArgs.ForceSetArg("-privatesendrounds", itostr(std::numeric_limits::max())); @@ -1740,7 +1743,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) LogPrintf("fLiteMode %d\n", fLiteMode); if(fLiteMode) { - InitWarning(_("You are starting in lite mode, all Dash-specific functionality is disabled.")); + InitWarning(_("You are starting in lite mode, most Dash-specific functionality is disabled.")); } if((!fLiteMode && fTxIndex == false) @@ -1996,17 +1999,26 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) nMaxRounds = std::numeric_limits::max(); } - privateSendClient.fEnablePrivateSend = gArgs.GetBoolArg("-enableprivatesend", false); + if (pwalletMain == nullptr) { + privateSendClient.fEnablePrivateSend = privateSendClient.fPrivateSendRunning = false; + } else { + privateSendClient.fEnablePrivateSend = gArgs.GetBoolArg("-enableprivatesend", !fLiteMode); + privateSendClient.fPrivateSendRunning = pwalletMain->IsLocked() ? false : gArgs.GetBoolArg("-privatesendautostart", DEFAULT_PRIVATESEND_AUTOSTART); + } privateSendClient.fPrivateSendMultiSession = gArgs.GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION); privateSendClient.nPrivateSendSessions = std::min(std::max((int)gArgs.GetArg("-privatesendsessions", DEFAULT_PRIVATESEND_SESSIONS), MIN_PRIVATESEND_SESSIONS), MAX_PRIVATESEND_SESSIONS); privateSendClient.nPrivateSendRounds = std::min(std::max((int)gArgs.GetArg("-privatesendrounds", DEFAULT_PRIVATESEND_ROUNDS), MIN_PRIVATESEND_ROUNDS), nMaxRounds); privateSendClient.nPrivateSendAmount = std::min(std::max((int)gArgs.GetArg("-privatesendamount", DEFAULT_PRIVATESEND_AMOUNT), MIN_PRIVATESEND_AMOUNT), MAX_PRIVATESEND_AMOUNT); privateSendClient.nPrivateSendDenoms = std::min(std::max((int)gArgs.GetArg("-privatesenddenoms", DEFAULT_PRIVATESEND_DENOMS), MIN_PRIVATESEND_DENOMS), MAX_PRIVATESEND_DENOMS); - LogPrintf("PrivateSend liquidityprovider: %d\n", privateSendClient.nLiquidityProvider); - LogPrintf("PrivateSend rounds: %d\n", privateSendClient.nPrivateSendRounds); - LogPrintf("PrivateSend amount: %d\n", privateSendClient.nPrivateSendAmount); - LogPrintf("PrivateSend denoms: %d\n", privateSendClient.nPrivateSendDenoms); + if (privateSendClient.fEnablePrivateSend) { + LogPrintf("PrivateSend: liquidityprovider=%d, autostart=%d, multisession=%d, " + "sessions=%d, rounds=%d, amount=%d, denoms=%d\n", + privateSendClient.nLiquidityProvider, privateSendClient.fPrivateSendRunning, + privateSendClient.fPrivateSendMultiSession, privateSendClient.nPrivateSendSessions, + privateSendClient.nPrivateSendRounds, privateSendClient.nPrivateSendAmount, + privateSendClient.nPrivateSendDenoms); + } #endif // ENABLE_WALLET CPrivateSend::InitStandardDenominations(); @@ -2062,17 +2074,19 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) if (!fLiteMode) { scheduler.scheduleEvery(boost::bind(&CNetFulfilledRequestManager::DoMaintenance, boost::ref(netfulfilledman)), 60 * 1000); scheduler.scheduleEvery(boost::bind(&CMasternodeSync::DoMaintenance, boost::ref(masternodeSync), boost::ref(*g_connman)), 1 * 1000); - scheduler.scheduleEvery(boost::bind(&CMasternodeUtils::DoMaintenance, boost::ref(*g_connman)), 1 * 1000); scheduler.scheduleEvery(boost::bind(&CGovernanceManager::DoMaintenance, boost::ref(governance), boost::ref(*g_connman)), 60 * 5 * 1000); scheduler.scheduleEvery(boost::bind(&CInstantSend::DoMaintenance, boost::ref(instantsend)), 60 * 1000); + } + + scheduler.scheduleEvery(boost::bind(&CMasternodeUtils::DoMaintenance, boost::ref(*g_connman)), 1 * 1000); - if (fMasternodeMode) - scheduler.scheduleEvery(boost::bind(&CPrivateSendServer::DoMaintenance, boost::ref(privateSendServer), boost::ref(*g_connman)), 1 * 1000); + if (fMasternodeMode) { + scheduler.scheduleEvery(boost::bind(&CPrivateSendServer::DoMaintenance, boost::ref(privateSendServer), boost::ref(*g_connman)), 1 * 1000); #ifdef ENABLE_WALLET - else - scheduler.scheduleEvery(boost::bind(&CPrivateSendClientManager::DoMaintenance, boost::ref(privateSendClient), boost::ref(*g_connman)), 1 * 1000); + } else if (privateSendClient.fEnablePrivateSend) { + scheduler.scheduleEvery(boost::bind(&CPrivateSendClientManager::DoMaintenance, boost::ref(privateSendClient), boost::ref(*g_connman)), 1 * 1000); #endif // ENABLE_WALLET } diff --git a/src/masternode/masternode-utils.cpp b/src/masternode/masternode-utils.cpp index 90c8debdf40c..551d5a50485b 100644 --- a/src/masternode/masternode-utils.cpp +++ b/src/masternode/masternode-utils.cpp @@ -92,8 +92,6 @@ void CMasternodeUtils::ProcessMasternodeConnections(CConnman& connman) void CMasternodeUtils::DoMaintenance(CConnman& connman) { - if(fLiteMode) return; // disable all Dash specific functionality - if(!masternodeSync.IsBlockchainSynced() || ShutdownRequested()) return; diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index 1ed0fd13290b..2e6a08ddc855 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -25,12 +25,12 @@ CPrivateSendClientManager privateSendClient; void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman) { if (fMasternodeMode) return; - if (fLiteMode) return; // ignore all Dash related functionality + if (!fEnablePrivateSend) return; if (!masternodeSync.IsBlockchainSynced()) return; if (!CheckDiskSpace()) { ResetPool(); - fEnablePrivateSend = false; + fPrivateSendRunning = false; LogPrintf("CPrivateSendClientManager::ProcessMessage -- Not enough disk space, disabling PrivateSend.\n"); return; } @@ -131,7 +131,7 @@ void CPrivateSendClientManager::ProcessMessage(CNode* pfrom, const std::string& void CPrivateSendClientSession::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman) { if (fMasternodeMode) return; - if (fLiteMode) return; // ignore all Dash related functionality + if (!privateSendClient.fEnablePrivateSend) return; if (!masternodeSync.IsBlockchainSynced()) return; if (strCommand == NetMsgType::DSSTATUSUPDATE) { @@ -265,7 +265,7 @@ void CPrivateSendClientSession::SetNull() // void CPrivateSendClientSession::UnlockCoins() { - if (!pwalletMain) return; + if (!privateSendClient.fEnablePrivateSend) return; while (true) { TRY_LOCK(pwalletMain->cs_wallet, lockWallet); @@ -428,7 +428,7 @@ void CPrivateSendClientManager::CheckTimeout() CheckQueue(); - if (!fEnablePrivateSend) return; + if (!fEnablePrivateSend || !fPrivateSendRunning) return; LOCK(cs_deqsessions); for (auto& session : deqSessions) { @@ -548,7 +548,7 @@ bool CPrivateSendClientSession::CheckPoolStateUpdate(CPrivateSendStatusUpdate ps // bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTransactionNew, CNode* pnode, CConnman& connman) { - if (!pwalletMain) return false; + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (fMasternodeMode || pnode == nullptr) return false; if (!mixingMasternode) return false; @@ -699,18 +699,13 @@ bool CPrivateSendClientManager::WaitForAnotherBlock() bool CPrivateSendClientManager::CheckAutomaticBackup() { - if (!pwalletMain) { - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Wallet is not initialized, no mixing available.\n"); - strAutoDenomResult = _("Wallet is not initialized") + ", " + _("no mixing available."); - fEnablePrivateSend = false; // no mixing - return false; - } + if (!fEnablePrivateSend || !fPrivateSendRunning) return false; switch (nWalletBackups) { case 0: LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Automatic backups disabled, no mixing available.\n"); strAutoDenomResult = _("Automatic backups disabled") + ", " + _("no mixing available."); - fEnablePrivateSend = false; // stop mixing + fPrivateSendRunning = false; // stop mixing pwalletMain->nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup" return false; case -1: @@ -734,7 +729,7 @@ bool CPrivateSendClientManager::CheckAutomaticBackup() LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d, no mixing available.\n", pwalletMain->nKeysLeftSinceAutoBackup); strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + ", " + _("no mixing available."), pwalletMain->nKeysLeftSinceAutoBackup); // It's getting really dangerous, stop mixing - fEnablePrivateSend = false; + fPrivateSendRunning = false; return false; } else if (pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { // Low number of keys left but it's still more or less safe to continue @@ -782,10 +777,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool return false; } - if (!pwalletMain) { - strAutoDenomResult = _("Wallet is not initialized"); - return false; - } + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; CAmount nBalanceNeedsAnonymized; @@ -953,18 +945,13 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool fDryRun) { if (fMasternodeMode) return false; // no client-side mixing on masternodes - if (!fEnablePrivateSend) return false; + if (!fEnablePrivateSend || !fPrivateSendRunning) return false; if (!masternodeSync.IsBlockchainSynced()) { strAutoDenomResult = _("Can't mix while sync in progress."); return false; } - if (!pwalletMain) { - strAutoDenomResult = _("Wallet is not initialized"); - return false; - } - if (!fDryRun && pwalletMain->IsLocked(true)) { strAutoDenomResult = _("Wallet is locked."); return false; @@ -1048,7 +1035,7 @@ CDeterministicMNCPtr CPrivateSendClientManager::GetRandomNotUsedMasternode() bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman) { - if (!pwalletMain) return false; + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; auto mnList = deterministicMNManager->GetListAtChainTip(); @@ -1116,7 +1103,7 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize bool CPrivateSendClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CConnman& connman) { - if (!pwalletMain) return false; + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (nBalanceNeedsAnonymized <= 0) return false; int nTries = 0; @@ -1283,10 +1270,7 @@ bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman) bool CPrivateSendClientSession::SelectDenominate(std::string& strErrorRet, std::vector >& vecPSInOutPairsRet) { - if (!pwalletMain) { - strErrorRet = "Wallet is not initialized"; - return false; - } + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; if (pwalletMain->IsLocked(true)) { strErrorRet = "Wallet locked, unable to create transaction!"; @@ -1392,7 +1376,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds // Create collaterals by looping through inputs grouped by addresses bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman) { - if (!pwalletMain) return false; + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; std::vector vecTally; if (!pwalletMain->SelectCoinsGroupedByAddresses(vecTally, false, false)) { @@ -1425,7 +1409,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman) // Split up large inputs or create fee sized inputs bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& tallyItem, bool fTryDenominated, CConnman& connman) { - if (!pwalletMain) return false; + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1501,7 +1485,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta // Create denominations by looping through inputs grouped by addresses bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, CConnman& connman) { - if (!pwalletMain) return false; + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; LOCK2(cs_main, pwalletMain->cs_wallet); @@ -1534,7 +1518,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // Create denominations bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, const CompactTallyItem& tallyItem, bool fCreateMixingCollaterals, CConnman& connman) { - if (!pwalletMain) return false; + if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; std::vector vecSend; CKeyHolderStorage keyHolderStorageDenom; @@ -1679,7 +1663,7 @@ void CPrivateSendClientManager::UpdatedBlockTip(const CBlockIndex* pindex) void CPrivateSendClientManager::DoMaintenance(CConnman& connman) { - if (fLiteMode) return; // disable all Dash specific functionality + if (!fEnablePrivateSend) return; if (fMasternodeMode) return; // no client-side mixing on masternodes if (!masternodeSync.IsBlockchainSynced() || ShutdownRequested()) return; diff --git a/src/privatesend/privatesend-client.h b/src/privatesend/privatesend-client.h index 73f66cf79fd5..a7633b577785 100644 --- a/src/privatesend/privatesend-client.h +++ b/src/privatesend/privatesend-client.h @@ -32,6 +32,7 @@ static const int DEFAULT_PRIVATESEND_AMOUNT = 1000; static const int DEFAULT_PRIVATESEND_DENOMS = 300; static const int DEFAULT_PRIVATESEND_LIQUIDITY = 0; +static const bool DEFAULT_PRIVATESEND_AUTOSTART = false; static const bool DEFAULT_PRIVATESEND_MULTISESSION = false; // Warn user if mixing in gui or try to create backup if mixing in daemon mode @@ -199,6 +200,7 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager int nPrivateSendDenoms; int nLiquidityProvider; bool fEnablePrivateSend; + bool fPrivateSendRunning; bool fPrivateSendMultiSession; int nCachedNumBlocks; //used for the overview screen @@ -217,6 +219,7 @@ class CPrivateSendClientManager : public CPrivateSendBaseManager nPrivateSendDenoms(DEFAULT_PRIVATESEND_DENOMS), nLiquidityProvider(DEFAULT_PRIVATESEND_LIQUIDITY), fEnablePrivateSend(false), + fPrivateSendRunning(false), fPrivateSendMultiSession(DEFAULT_PRIVATESEND_MULTISESSION), nCachedNumBlocks(std::numeric_limits::max()), fCreateAutoBackups(true) diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 5792bcee1f96..30c694eaab36 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -503,7 +503,7 @@ void CPrivateSend::CheckDSTXes(int nHeight) void CPrivateSend::UpdatedBlockTip(const CBlockIndex* pindex) { - if (pindex && !fLiteMode && masternodeSync.IsBlockchainSynced()) { + if (pindex && masternodeSync.IsBlockchainSynced()) { CheckDSTXes(pindex->nHeight); } } diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 6d2ef3bbbd20..9cbe884601dc 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -158,8 +158,7 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) // start with displaying the "out of sync" warnings showOutOfSyncWarning(true); - // that's it for litemode - if(fLiteMode) return; + if(!privateSendClient.fEnablePrivateSend) return; // Disable any PS UI for masternode or when autobackup is disabled or failed for whatever reason if(fMasternodeMode || nWalletBackups <= 0){ @@ -168,7 +167,7 @@ OverviewPage::OverviewPage(const PlatformStyle *platformStyle, QWidget *parent) ui->labelPrivateSendEnabled->setToolTip(tr("Automatic backups are disabled, no mixing available!")); } } else { - if(!privateSendClient.fEnablePrivateSend){ + if(!privateSendClient.fPrivateSendRunning){ ui->togglePrivateSend->setText(tr("Start Mixing")); } else { ui->togglePrivateSend->setText(tr("Stop Mixing")); @@ -291,8 +290,8 @@ void OverviewPage::setWalletModel(WalletModel *model) // explicitly update PS frame and transaction list to reflect actual settings updateAdvancedPSUI(model->getOptionsModel()->getShowAdvancedPSUI()); - // that's it for litemode - if(fLiteMode) return; + if(!privateSendClient.fEnablePrivateSend) return; + connect(model->getOptionsModel(), SIGNAL(privateSendRoundsChanged()), this, SLOT(updatePrivateSendProgress())); connect(model->getOptionsModel(), SIGNAL(privateSentAmountChanged()), this, SLOT(updatePrivateSendProgress())); connect(model->getOptionsModel(), SIGNAL(advancedPSUIChanged(bool)), this, SLOT(updateAdvancedPSUI(bool))); @@ -448,10 +447,10 @@ void OverviewPage::updatePrivateSendProgress() void OverviewPage::updateAdvancedPSUI(bool fShowAdvancedPSUI) { this->fShowAdvancedPSUI = fShowAdvancedPSUI; - int nNumItems = (fLiteMode || !fShowAdvancedPSUI) ? NUM_ITEMS : NUM_ITEMS_ADV; + int nNumItems = (!privateSendClient.fEnablePrivateSend || !fShowAdvancedPSUI) ? NUM_ITEMS : NUM_ITEMS_ADV; SetupTransactionList(nNumItems); - if (fLiteMode) return; + if (!privateSendClient.fEnablePrivateSend) return; ui->framePrivateSend->setVisible(true); ui->labelCompletitionText->setVisible(fShowAdvancedPSUI); @@ -481,7 +480,7 @@ void OverviewPage::privateSendStatus() } ui->labelPrivateSendEnabled->setToolTip(strKeysLeftText); - if (!privateSendClient.fEnablePrivateSend) { + if (!privateSendClient.fPrivateSendRunning) { if (nBestHeight != privateSendClient.nCachedNumBlocks) { privateSendClient.nCachedNumBlocks = nBestHeight; updatePrivateSendProgress(); @@ -538,7 +537,7 @@ void OverviewPage::privateSendStatus() } } - QString strEnabled = privateSendClient.fEnablePrivateSend ? tr("Enabled") : tr("Disabled"); + QString strEnabled = privateSendClient.fPrivateSendRunning ? tr("Enabled") : tr("Disabled"); // Show how many keys left in advanced PS UI mode only if(fShowAdvancedPSUI) strEnabled += ", " + strKeysLeftText; ui->labelPrivateSendEnabled->setText(strEnabled); @@ -605,7 +604,7 @@ void OverviewPage::togglePrivateSend(){ QMessageBox::Ok, QMessageBox::Ok); settings.setValue("hasMixed", "hasMixed"); } - if(!privateSendClient.fEnablePrivateSend){ + if(!privateSendClient.fPrivateSendRunning){ const CAmount nMinAmount = CPrivateSend::GetSmallestDenomination() + CPrivateSend::GetMaxCollateralAmount(); if(currentBalance < nMinAmount){ QString strMinAmount(BitcoinUnits::formatWithUnit(nDisplayUnit, nMinAmount)); @@ -633,10 +632,10 @@ void OverviewPage::togglePrivateSend(){ } - privateSendClient.fEnablePrivateSend = !privateSendClient.fEnablePrivateSend; + privateSendClient.fPrivateSendRunning = !privateSendClient.fPrivateSendRunning; privateSendClient.nCachedNumBlocks = std::numeric_limits::max(); - if(!privateSendClient.fEnablePrivateSend){ + if(!privateSendClient.fPrivateSendRunning){ ui->togglePrivateSend->setText(tr("Start Mixing")); privateSendClient.ResetPool(); } else { @@ -670,5 +669,5 @@ void OverviewPage::DisablePrivateSendCompletely() { if (nWalletBackups <= 0) { ui->labelPrivateSendEnabled->setText("(" + tr("Disabled") + ")"); } - privateSendClient.fEnablePrivateSend = false; + privateSendClient.fPrivateSendRunning = false; } diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index b50f73aeab80..f4841446a8f7 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -25,6 +25,7 @@ #include "wallet/wallet.h" #include "privatesend/privatesend.h" +#include "privatesend/privatesend-client.h" #include #include @@ -87,24 +88,27 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p if (!settings.contains("bUseInstantSend")) settings.setValue("bUseInstantSend", false); - bool fUsePrivateSend = settings.value("bUsePrivateSend").toBool(); - bool fUseInstantSend = settings.value("bUseInstantSend").toBool(); - if(fLiteMode) { + if (!privateSendClient.fEnablePrivateSend) { ui->checkUsePrivateSend->setChecked(false); ui->checkUsePrivateSend->setVisible(false); - ui->checkUseInstantSend->setVisible(false); CoinControlDialog::coinControl->fUsePrivateSend = false; - CoinControlDialog::coinControl->fUseInstantSend = false; - } - else{ + } else { + bool fUsePrivateSend = settings.value("bUsePrivateSend").toBool(); ui->checkUsePrivateSend->setChecked(fUsePrivateSend); - ui->checkUseInstantSend->setChecked(fUseInstantSend); CoinControlDialog::coinControl->fUsePrivateSend = fUsePrivateSend; - CoinControlDialog::coinControl->fUseInstantSend = fUseInstantSend; + connect(ui->checkUsePrivateSend, SIGNAL(stateChanged ( int )), this, SLOT(updateDisplayUnit())); } - connect(ui->checkUsePrivateSend, SIGNAL(stateChanged ( int )), this, SLOT(updateDisplayUnit())); - connect(ui->checkUseInstantSend, SIGNAL(stateChanged ( int )), this, SLOT(updateInstantSend())); + if (fLiteMode) { + ui->checkUseInstantSend->setChecked(false); + ui->checkUseInstantSend->setVisible(false); + CoinControlDialog::coinControl->fUseInstantSend = false; + } else{ + bool fUseInstantSend = settings.value("bUseInstantSend").toBool(); + ui->checkUseInstantSend->setChecked(fUseInstantSend); + CoinControlDialog::coinControl->fUseInstantSend = fUseInstantSend; + connect(ui->checkUseInstantSend, SIGNAL(stateChanged ( int )), this, SLOT(updateInstantSend())); + } // Coin Control: clipboard actions QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this); diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 5efeeb2500fd..6e4747494af9 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -51,6 +51,20 @@ UniValue privatesend(const JSONRPCRequest& request) if (fMasternodeMode) throw JSONRPCError(RPC_INTERNAL_ERROR, "Client-side mixing is not supported on masternodes"); + if (!privateSendClient.fEnablePrivateSend) { + if (fLiteMode) { + // mixing is disabled by default in lite mode + throw JSONRPCError(RPC_INTERNAL_ERROR, "Mixing is disabled in lite mode, use -enableprivatesend command line option to enable mixing again"); + } else if (!gArgs.GetBoolArg("-enableprivatesend", true)) { + // otherwise it's on by default, unless cmd line option says otherwise + throw JSONRPCError(RPC_INTERNAL_ERROR, "Mixing is disabled via -enableprivatesend=0 command line option, remove it to enable mixing again"); + } else { + // neither litemode nor enableprivatesend=false casee, + // most likely smth bad happened and we disabled it while running the wallet + throw JSONRPCError(RPC_INTERNAL_ERROR, "Mixing is disabled due to some internal error"); + } + } + if (request.params[0].get_str() == "start") { { LOCK(pwallet->cs_wallet); @@ -58,13 +72,13 @@ UniValue privatesend(const JSONRPCRequest& request) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please unlock wallet for mixing with walletpassphrase first."); } - privateSendClient.fEnablePrivateSend = true; + privateSendClient.fPrivateSendRunning = true; bool result = privateSendClient.DoAutomaticDenominating(*g_connman); return "Mixing " + (result ? "started successfully" : ("start failed: " + privateSendClient.GetStatuses() + ", will retry")); } if (request.params[0].get_str() == "stop") { - privateSendClient.fEnablePrivateSend = false; + privateSendClient.fPrivateSendRunning = false; return "Mixing was stopped"; } diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 7ae798df0447..1f0aa119d510 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -99,8 +99,7 @@ UniValue getinfo(const JSONRPCRequest& request) if (pwallet) { obj.push_back(Pair("walletversion", pwallet->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance()))); - if(!fLiteMode) - obj.push_back(Pair("privatesend_balance", ValueFromAmount(pwallet->GetAnonymizedBalance()))); + obj.push_back(Pair("privatesend_balance", ValueFromAmount(pwallet->GetAnonymizedBalance()))); } #endif obj.push_back(Pair("blocks", (int)chainActive.Height())); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b08a4abc2df8..e2fa147e3e2e 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2507,8 +2507,7 @@ UniValue getwalletinfo(const JSONRPCRequest& request) "{\n" " \"walletversion\": xxxxx, (numeric) the wallet version\n" " \"balance\": xxxxxxx, (numeric) the total confirmed balance of the wallet in " + CURRENCY_UNIT + "\n" - + (!fLiteMode ? - " \"privatesend_balance\": xxxxxx, (numeric) the anonymized dash balance of the wallet in " + CURRENCY_UNIT + "\n" : "") + + " \"privatesend_balance\": xxxxxx, (numeric) the anonymized dash balance of the wallet in " + CURRENCY_UNIT + "\n" " \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed balance of the wallet in " + CURRENCY_UNIT + "\n" " \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet in " + CURRENCY_UNIT + "\n" " \"txcount\": xxxxxxx, (numeric) the total number of transactions in the wallet\n" @@ -2541,8 +2540,7 @@ UniValue getwalletinfo(const JSONRPCRequest& request) UniValue obj(UniValue::VOBJ); obj.push_back(Pair("walletversion", pwallet->GetVersion())); obj.push_back(Pair("balance", ValueFromAmount(pwallet->GetBalance()))); - if(!fLiteMode) - obj.push_back(Pair("privatesend_balance", ValueFromAmount(pwallet->GetAnonymizedBalance()))); + obj.push_back(Pair("privatesend_balance", ValueFromAmount(pwallet->GetAnonymizedBalance()))); obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance()))); obj.push_back(Pair("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance()))); obj.push_back(Pair("txcount", (int)pwallet->mapWallet.size())); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 70e92f9d64ab..1d04c099940f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2318,7 +2318,7 @@ CAmount CWallet::GetBalance() const CAmount CWallet::GetAnonymizableBalance(bool fSkipDenominated, bool fSkipUnconfirmed) const { - if(fLiteMode) return 0; + if(!privateSendClient.fEnablePrivateSend) return 0; std::vector vecTally; if(!SelectCoinsGroupedByAddresses(vecTally, fSkipDenominated, true, fSkipUnconfirmed)) return 0; @@ -2340,7 +2340,7 @@ CAmount CWallet::GetAnonymizableBalance(bool fSkipDenominated, bool fSkipUnconfi CAmount CWallet::GetAnonymizedBalance() const { - if(fLiteMode) return 0; + if(!privateSendClient.fEnablePrivateSend) return 0; CAmount nTotal = 0; @@ -2364,7 +2364,7 @@ CAmount CWallet::GetAnonymizedBalance() const // that's ok as long as we use it for informational purposes only float CWallet::GetAverageAnonymizedRounds() const { - if(fLiteMode) return 0; + if(!privateSendClient.fEnablePrivateSend) return 0; int nTotal = 0; int nCount = 0; @@ -2386,7 +2386,7 @@ float CWallet::GetAverageAnonymizedRounds() const // that's ok as long as we use it for informational purposes only CAmount CWallet::GetNormalizedAnonymizedBalance() const { - if(fLiteMode) return 0; + if(!privateSendClient.fEnablePrivateSend) return 0; CAmount nTotal = 0; @@ -2408,7 +2408,7 @@ CAmount CWallet::GetNormalizedAnonymizedBalance() const CAmount CWallet::GetDenominatedBalance(bool unconfirmed) const { - if(fLiteMode) return 0; + if(!privateSendClient.fEnablePrivateSend) return 0; CAmount nTotal = 0; @@ -4067,7 +4067,7 @@ bool CWallet::NewKeyPool() walletdb.ErasePool(nIndex); } setExternalKeyPool.clear(); - privateSendClient.fEnablePrivateSend = false; + privateSendClient.fPrivateSendRunning = false; nKeysLeftSinceAutoBackup = 0; if (!TopUpKeyPool()) From 09b017fc534514a3d591a9e80df1256a506d9d5d Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Thu, 27 Jun 2019 22:25:02 +0200 Subject: [PATCH 319/987] Only load signingActiveQuorumCount + 1 quorums into cache (#3002) No need to load 25 quorums when we're scanning for the larger quorums which only have 4 active quorums. This avoids loading thousands of masternode lists unnecessarily. --- src/llmq/quorums.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index ba5b90eb5991..c980e3021be7 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -313,7 +313,7 @@ std::vector CQuorumManager::ScanQuorums(Consensus::LLMQType llmqTyp auto& params = Params().GetConsensus().llmqs.at(llmqType); auto cacheKey = std::make_pair(llmqType, pindexStart->GetBlockHash()); - const size_t cacheMaxSize = 25; // largest active set + 1 + const size_t cacheMaxSize = params.signingActiveQuorumCount + 1; std::vector result; From 63424fb26a161ea53bb8783c5a71235e5af65604 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Thu, 27 Jun 2019 22:25:30 +0200 Subject: [PATCH 320/987] Fix 2 common Travis failures which happen when Travis has network issues (#3003) * Retry downloading of depends sources 3 times * Manually invoke apt-get update and install instead of using addon This allows us to use travis_retry on these operations. * Add exception for depends/Makefile in .gitignore * Remove --retry from curl call This avoids future confusion as we don't rely on curl anymore to properly retry downloads. curls does only retry on transient errors, while Travis might cause all kinds of errors which circumvent the retry logic of curl. --- .gitignore | 1 + .travis.yml | 13 ++++--------- depends/Makefile | 1 - depends/builders/darwin.mk | 2 +- depends/builders/linux.mk | 2 +- depends/funcs.mk | 2 ++ 6 files changed, 9 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index c3be44a72c15..a1c24fd7222f 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,7 @@ libconftest.dylib* Makefile dash-qt Dash-Qt.app +!/depends/Makefile # Unit-tests Makefile.test diff --git a/.travis.yml b/.travis.yml index 6ded5c378585..c27b6f03ae33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,19 +8,10 @@ dist: trusty os: linux language: generic -addons: - apt: - packages: - # Use more recent docker version - - docker-ce - # Can be removed if Travis ever upgrades to Bionic - - realpath - services: - docker cache: - apt: true ccache: true directories: - $HOME/cache @@ -122,6 +113,10 @@ before_cache: # Save builder image - docker save dash-builder-$BUILD_TARGET-$TRAVIS_JOB_NUMBER $(docker history -q dash-builder-$BUILD_TARGET-$TRAVIS_JOB_NUMBER | grep -v \) | gzip -2 > $HOME/cache/docker/dash-builder-$BUILD_TARGET.tar.gz +before_install: + - travis_retry travis_apt_get_update + - travis_retry sudo apt-get -yq --no-install-suggests --no-install-recommends install docker-ce realpath + install: # Our scripts try to be Travis agnostic - export PULL_REQUEST="$TRAVIS_PULL_REQUEST" diff --git a/depends/Makefile b/depends/Makefile index 71aa4ecb8a6b..6d8bd8d21424 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -14,7 +14,6 @@ PATCHES_PATH = $(BASEDIR)/patches BASEDIR = $(CURDIR) HASH_LENGTH:=11 DOWNLOAD_CONNECT_TIMEOUT:=10 -DOWNLOAD_RETRIES:=3 HOST_ID_SALT ?= salt BUILD_ID_SALT ?= salt diff --git a/depends/builders/darwin.mk b/depends/builders/darwin.mk index d15d6feea6f4..adf75e6ff598 100644 --- a/depends/builders/darwin.mk +++ b/depends/builders/darwin.mk @@ -7,7 +7,7 @@ build_darwin_OTOOL: = $(shell xcrun -f otool) build_darwin_NM: = $(shell xcrun -f nm) build_darwin_INSTALL_NAME_TOOL:=$(shell xcrun -f install_name_tool) build_darwin_SHA256SUM = shasum -a 256 -build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o +build_darwin_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) -o #darwin host on darwin builder. overrides darwin host preferences. darwin_CC=$(shell xcrun -f clang) -mmacosx-version-min=$(OSX_MIN_VERSION) diff --git a/depends/builders/linux.mk b/depends/builders/linux.mk index b03f42401047..9af0d066a086 100644 --- a/depends/builders/linux.mk +++ b/depends/builders/linux.mk @@ -1,2 +1,2 @@ build_linux_SHA256SUM = sha256sum -build_linux_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) --retry $(DOWNLOAD_RETRIES) -o +build_linux_DOWNLOAD = curl --location --fail --connect-timeout $(DOWNLOAD_CONNECT_TIMEOUT) -o diff --git a/depends/funcs.mk b/depends/funcs.mk index 15e404e42dcf..5c05a4e7c29c 100644 --- a/depends/funcs.mk +++ b/depends/funcs.mk @@ -31,6 +31,8 @@ endef define fetch_file ( test -f $$($(1)_source_dir)/$(4) || \ ( $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5)) || \ + (sleep 5 && $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5))) || \ + (sleep 10 && $(call fetch_file_inner,$(1),$(2),$(3),$(4),$(5))) || \ $(call fetch_file_inner,$(1),$(FALLBACK_DOWNLOAD_PATH),$(3),$(4),$(5)))) endef From 5809c5c3d017b301b9fba96462d25ae669b4d981 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Thu, 27 Jun 2019 22:25:59 +0200 Subject: [PATCH 321/987] Implement "quorum memberof" (#3004) * Implement BuildQuorumInfo and call it from quorum_info * Add type to result of BuildQuorumInfo * Implement "quorum memberof" --- src/rpc/rpcquorums.cpp | 121 +++++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 29 deletions(-) diff --git a/src/rpc/rpcquorums.cpp b/src/rpc/rpcquorums.cpp index 66218aab0215..4cfd5caf24a8 100644 --- a/src/rpc/rpcquorums.cpp +++ b/src/rpc/rpcquorums.cpp @@ -76,6 +76,41 @@ void quorum_info_help() ); } +UniValue BuildQuorumInfo(const llmq::CQuorumCPtr& quorum, bool includeMembers, bool includeSkShare) +{ + UniValue ret(UniValue::VOBJ); + + ret.push_back(Pair("height", quorum->height)); + ret.push_back(Pair("type", quorum->params.name)); + ret.push_back(Pair("quorumHash", quorum->qc.quorumHash.ToString())); + ret.push_back(Pair("minedBlock", quorum->minedBlockHash.ToString())); + + if (includeMembers) { + UniValue membersArr(UniValue::VARR); + for (size_t i = 0; i < quorum->members.size(); i++) { + auto& dmn = quorum->members[i]; + UniValue mo(UniValue::VOBJ); + mo.push_back(Pair("proTxHash", dmn->proTxHash.ToString())); + mo.push_back(Pair("valid", quorum->qc.validMembers[i])); + if (quorum->qc.validMembers[i]) { + CBLSPublicKey pubKey = quorum->GetPubKeyShare(i); + if (pubKey.IsValid()) { + mo.push_back(Pair("pubKeyShare", pubKey.ToString())); + } + } + membersArr.push_back(mo); + } + + ret.push_back(Pair("members", membersArr)); + } + ret.push_back(Pair("quorumPublicKey", quorum->qc.quorumPublicKey.ToString())); + CBLSSecretKey skShare = quorum->GetSkShare(); + if (includeSkShare && skShare.IsValid()) { + ret.push_back(Pair("secretKeyShare", skShare.ToString())); + } + return ret; +} + UniValue quorum_info(const JSONRPCRequest& request) { if (request.fHelp || (request.params.size() != 3 && request.params.size() != 4)) @@ -101,35 +136,7 @@ UniValue quorum_info(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "quorum not found"); } - UniValue ret(UniValue::VOBJ); - - ret.push_back(Pair("height", quorum->height)); - ret.push_back(Pair("quorumHash", quorum->qc.quorumHash.ToString())); - ret.push_back(Pair("minedBlock", quorum->minedBlockHash.ToString())); - - UniValue membersArr(UniValue::VARR); - for (size_t i = 0; i < quorum->members.size(); i++) { - auto& dmn = quorum->members[i]; - UniValue mo(UniValue::VOBJ); - mo.push_back(Pair("proTxHash", dmn->proTxHash.ToString())); - mo.push_back(Pair("valid", quorum->qc.validMembers[i])); - if (quorum->qc.validMembers[i]) { - CBLSPublicKey pubKey = quorum->GetPubKeyShare(i); - if (pubKey.IsValid()) { - mo.push_back(Pair("pubKeyShare", pubKey.ToString())); - } - } - membersArr.push_back(mo); - } - - ret.push_back(Pair("members", membersArr)); - ret.push_back(Pair("quorumPublicKey", quorum->qc.quorumPublicKey.ToString())); - CBLSSecretKey skShare = quorum->GetSkShare(); - if (includeSkShare && skShare.IsValid()) { - ret.push_back(Pair("secretKeyShare", skShare.ToString())); - } - - return ret; + return BuildQuorumInfo(quorum, true, includeSkShare); } void quorum_dkgstatus_help() @@ -182,6 +189,59 @@ UniValue quorum_dkgstatus(const JSONRPCRequest& request) return ret; } +void quorum_memberof_help() +{ + throw std::runtime_error( + "quorum memberof \"proTxHash\"\n" + "Checks which quorums the given masternode is a member of.\n" + "\nArguments:\n" + "1. \"proTxHash\" (string, required) ProTxHash of the masternode.\n" + ); +} + +UniValue quorum_memberof(const JSONRPCRequest& request) +{ + if (request.fHelp || (request.params.size() != 2)) { + quorum_memberof_help(); + } + + uint256 protxHash = ParseHashV(request.params[1], "proTxHash"); + + const CBlockIndex* pindexTip; + { + LOCK(cs_main); + pindexTip = chainActive.Tip(); + } + + auto mnList = deterministicMNManager->GetListForBlock(pindexTip->GetBlockHash()); + auto dmn = mnList.GetMN(protxHash); + if (!dmn) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "masternode not found"); + } + + std::set> quorumHashes; + for (const auto& p : Params().GetConsensus().llmqs) { + auto& params = p.second; + auto quorums = llmq::quorumManager->ScanQuorums(params.type, params.signingActiveQuorumCount); + for (auto& quorum : quorums) { + for (auto& m : quorum->members) { + if (m->proTxHash == dmn->proTxHash) { + quorumHashes.emplace(params.type, quorum->qc.quorumHash); + } + } + } + } + + UniValue result(UniValue::VARR); + for (auto& p : quorumHashes) { + auto quorum = llmq::quorumManager->GetQuorum(p.first, p.second); + assert(quorum); + result.push_back(BuildQuorumInfo(quorum, false, false)); + } + + return result; +} + void quorum_sign_help() { throw std::runtime_error( @@ -318,6 +378,7 @@ UniValue quorum_dkgsimerror(const JSONRPCRequest& request) " info - Return information about a quorum\n" " dkgsimerror - Simulates DKG errors and malicious behavior.\n" " dkgstatus - Return the status of the current DKG process\n" + " memberof - Checks which quorums the given masternode is a member of\n" " sign - Threshold-sign a message\n" " hasrecsig - Test if a valid recovered signature is present\n" " getrecsig - Get a recovered signature\n" @@ -342,6 +403,8 @@ UniValue quorum(const JSONRPCRequest& request) return quorum_info(request); } else if (command == "dkgstatus") { return quorum_dkgstatus(request); + } else if (command == "memberof") { + return quorum_memberof(request); } else if (command == "sign" || command == "hasrecsig" || command == "getrecsig" || command == "isconflicting") { return quorum_sigs_cmd(request); } else if (command == "dkgsimerror") { From d5d27ad19bd2c16644ce438e610e656b087f1208 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 1 Jul 2019 07:58:31 -0500 Subject: [PATCH 322/987] s/bitcoind/dashd Signed-off-by: Pasta --- src/wallet/rpcdump.cpp | 2 +- src/wallet/test/wallet_tests.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 7f35bd6fefcb..5d30d4cab064 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1363,7 +1363,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) "block from time %d, which is after or within %d seconds of key creation, and " "could contain transactions pertaining to the key. As a result, transactions " "and coins using this key may not appear in the wallet. This error could be " - "caused by pruning or data corruption (see bitcoind log for details) and could " + "caused by pruning or data corruption (see dashd log for details) and could " "be dealt with by downloading and rescanning the relevant blocks (see -reindex " "and -rescan options).", GetImportTimestamp(request, now), scanFailed->GetBlockTimeMax(), TIMESTAMP_WINDOW))); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 9354aec88684..31ea7a59d5ed 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -429,7 +429,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) "timestamp %d. There was an error reading a block from time %d, which is after or within %d " "seconds of key creation, and could contain transactions pertaining to the key. As a result, " "transactions and coins using this key may not appear in the wallet. This error could be caused " - "by pruning or data corruption (see bitcoind log for details) and could be dealt with by " + "by pruning or data corruption (see dashd log for details) and could be dealt with by " "downloading and rescanning the relevant blocks (see -reindex and -rescan " "options).\"}},{\"success\":true}]", 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); From 6ad8fe0e9fb46eaf122ae9b54c9875e14ae69b00 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 1 Jul 2019 08:00:23 -0500 Subject: [PATCH 323/987] adjust CoinType logic Signed-off-by: Pasta --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5143a199db54..fcbdbef26d5d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2602,7 +2602,7 @@ void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint((*it).first, i))) continue; - if (IsLockedCoin((*it).first, i) || nCoinType == ONLY_1000) + if (IsLockedCoin((*it).first, i) || nCoinType != ONLY_1000) continue; if (IsSpent(wtxid, i)) From 6ce3e55cb4519b78f15b126644e166505e44b362 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 1 Jul 2019 13:44:40 -0500 Subject: [PATCH 324/987] add extra params to AvailableCoins calls Signed-off-by: Pasta --- src/rpc/masternode.cpp | 2 +- src/wallet/wallet.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 5efeeb2500fd..80102a71f7f0 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -320,7 +320,7 @@ UniValue masternode_outputs(const JSONRPCRequest& request) // Find possible candidates std::vector vPossibleCoins; - pwallet->AvailableCoins(vPossibleCoins, true, NULL, false, ONLY_1000); + pwallet->AvailableCoins(vPossibleCoins, true, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_1000); UniValue obj(UniValue::VOBJ); for (const auto& out : vPossibleCoins) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fcbdbef26d5d..bad6e3d442c8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3041,7 +3041,7 @@ bool CWallet::SelectPSInOutPairsByDenominations(int nDenom, CAmount nValueMin, C return false; } - AvailableCoins(vCoins, true, NULL, false, ONLY_DENOMINATED); + AvailableCoins(vCoins, true, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_DENOMINATED); LogPrintf("CWallet::%s -- vCoins.size(): %d\n", __func__, vCoins.size()); std::random_shuffle(vCoins.rbegin(), vCoins.rend(), GetRandInt); @@ -3183,7 +3183,7 @@ bool CWallet::SelectPrivateCoins(CAmount nValueMin, CAmount nValueMax, std::vect nValueRet = 0; std::vector vCoins; - AvailableCoins(vCoins, true, coinControl, false, nPrivateSendRoundsMin < 0 ? ONLY_NONDENOMINATED : ONLY_DENOMINATED); + AvailableCoins(vCoins, true, coinControl, 0, MAX_MONEY, MAX_MONEY, 0, false, nPrivateSendRoundsMin < 0 ? ONLY_NONDENOMINATED : ONLY_DENOMINATED); //order the array so largest nondenom are first, then denominations, then very small inputs. std::sort(vCoins.rbegin(), vCoins.rend(), CompareByPriority()); @@ -3217,7 +3217,7 @@ bool CWallet::GetCollateralTxDSIn(CTxDSIn& txdsinRet, CAmount& nValueRet) const std::vector vCoins; - AvailableCoins(vCoins, true, NULL, false, ONLY_PRIVATESEND_COLLATERAL); + AvailableCoins(vCoins, true, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_PRIVATESEND_COLLATERAL); if (vCoins.empty()) { return false; @@ -3236,7 +3236,7 @@ bool CWallet::GetMasternodeOutpointAndKeys(COutPoint& outpointRet, CPubKey& pubK // Find possible candidates std::vector vPossibleCoins; - AvailableCoins(vPossibleCoins, true, NULL, false, ONLY_1000); + AvailableCoins(vPossibleCoins, true, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_1000); if(vPossibleCoins.empty()) { LogPrintf("CWallet::GetMasternodeOutpointAndKeys -- Could not locate any valid masternode vin\n"); return false; @@ -3307,7 +3307,7 @@ int CWallet::CountInputsWithAmount(CAmount nInputAmount) const bool CWallet::HasCollateralInputs(bool fOnlyConfirmed) const { std::vector vCoins; - AvailableCoins(vCoins, fOnlyConfirmed, NULL, false, ONLY_PRIVATESEND_COLLATERAL); + AvailableCoins(vCoins, fOnlyConfirmed, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_PRIVATESEND_COLLATERAL); return !vCoins.empty(); } @@ -3476,7 +3476,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT LOCK2(cs_main, cs_wallet); { std::vector vAvailableCoins; - AvailableCoins(vAvailableCoins, true, coinControl, false, nCoinType, fUseInstantSend); + AvailableCoins(vAvailableCoins, true, coinControl, 0, MAX_MONEY, MAX_MONEY, 0, false, nCoinType, fUseInstantSend); int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired; nFeeRet = 0; From 9adb72e1121a782c19296227ea01ecacd7fdd204 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 1 Jul 2019 13:48:19 -0500 Subject: [PATCH 325/987] remove initialize to 0 in chainparams.h Signed-off-by: Pasta --- src/chainparams.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/chainparams.h b/src/chainparams.h index 0da6db3a863b..2a0a2b597190 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -115,9 +115,9 @@ class CChainParams bool fAllowMultiplePorts; CCheckpointData checkpointData; ChainTxData chainTxData; - int nPoolMinParticipants{0}; - int nPoolMaxParticipants{0}; - int nFulfilledRequestExpireTime{0}; + int nPoolMinParticipants; + int nPoolMaxParticipants; + int nFulfilledRequestExpireTime; std::vector vSporkAddresses; int nMinSporkKeys; bool fBIP9CheckMasternodesUpgraded; From 780bffeb78d7b791f696a9446ee7c21c38c0aa39 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 2 Jul 2019 06:16:11 +0200 Subject: [PATCH 326/987] Enable stacktrace support in gitian builds (#3006) * Remove use of -rdynamic This causes check-symbols to fail horribly and also turned out to be not required when using libbacktrace. It was only required when using "backtrace()" from "" * Remove spurious ], from configure.ac * Add -DENABLE_STACKTRACES=1 to CMakeLists.txt * Remove unused method my_backtrace_simple_callback * Use fs::path().filename() instead of basename() * Add static g_exeFileName and g_exeFileBaseName * Use .exe.dbg file when available * Use uint64_t instead of uintptr_t * Implement GetBaseAddress() for unix and win32 * Implement unified crash_info and use it everywhere before printing crash info * Print a serialized version of crash_info when there is no debug info * Implement "-printcrashinfo" command line option * Compile stacktrace support unconditionally and only make crash hooks conditional This also renames the --enable-stacktraces option to --enable-crash-hooks * Enable crash hooks in win/linux Gitian builds * Try to load .debug file on MacOS and enable crash hooks for osx Gitian builds * Check for dsymutil and if it needs --flat * Create .debug files in osx Gitian build * Handle review comments * Also print crash description when no stacktrace is available * Unconditionally add -g1 debug information Instead of making it dependent on "--enable-crash-hooks". We will need the debug info every time now, even in release builds. * Put MacOS debug info into dSYM symbols instead of plain .debug files * Implement MacOS specific GetBaseAddress --- CMakeLists.txt | 1 + configure.ac | 47 ++- contrib/gitian-descriptors/gitian-linux.yml | 2 +- contrib/gitian-descriptors/gitian-osx.yml | 10 +- contrib/gitian-descriptors/gitian-win.yml | 2 +- src/Makefile.am | 14 +- src/dash-cli.cpp | 6 + src/dash-tx.cpp | 5 + src/dashd.cpp | 5 + src/qt/dash.cpp | 7 + src/stacktraces.cpp | 409 ++++++++++++++------ src/stacktraces.h | 4 +- src/util.cpp | 2 +- 13 files changed, 370 insertions(+), 144 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 962bf77ead40..670d3e3391eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ if(DEFINED DEPENDS_PREFIX) endif() add_definitions( + -DENABLE_CRASH_HOOKS=1 -DENABLE_WALLET=1 ) diff --git a/configure.ac b/configure.ac index 33b1244bd4ff..7c83915e7eb4 100644 --- a/configure.ac +++ b/configure.ac @@ -87,6 +87,7 @@ AC_PATH_PROG(HEXDUMP,hexdump) AC_PATH_TOOL(READELF, readelf) AC_PATH_TOOL(CPPFILT, c++filt) AC_PATH_TOOL(OBJCOPY, objcopy) +AC_PATH_TOOL(DSYMUTIL, dsymutil) AC_ARG_VAR(PYTHONPATH, Augments the default search path for python module files) @@ -192,12 +193,12 @@ AC_ARG_ENABLE([debug], [enable_debug=$enableval], [enable_debug=no]) -# Enable exception stacktraces -AC_ARG_ENABLE([stacktraces], - [AS_HELP_STRING([--enable-stacktraces], - [gather and print exception stack traces (default is no)])], - [enable_stacktraces=$enableval], - [enable_stacktraces=no]) +# Enable crash hooks +AC_ARG_ENABLE([crash-hooks], + [AS_HELP_STRING([--enable-crash-hooks], + [hook into exception/signal/assert handling to gather stack traces (default is no)])], + [enable_crashhooks=$enableval], + [enable_crashhooks=no]) # Enable in-wallet miner AC_ARG_ENABLE([miner], @@ -229,9 +230,10 @@ if test "x$enable_debug" = xyes; then if test "x$GXX" = xyes; then CXXFLAGS="$CXXFLAGS -g3 -O0" fi -elif test "x$enable_stacktraces" = xyes; then - # Enable debug information but don't turn off optimization - # (stacktraces will be suboptimal, but better than nothing) +else + # We always enable at at least -g1 debug info to support proper stacktraces in crash infos + # Stacktraces will be suboptimal due to optimization, but better than nothing. Also, -fno-omit-frame-pointer + # mitigates this a little bit if test "x$GCC" = xyes; then CFLAGS="$CFLAGS -g1 -fno-omit-frame-pointer" fi @@ -241,17 +243,15 @@ elif test "x$enable_stacktraces" = xyes; then fi fi -AM_CONDITIONAL([ENABLE_STACKTRACES], [test x$enable_stacktraces = xyes]) -if test "x$enable_stacktraces" = xyes; then - AC_DEFINE(ENABLE_STACKTRACES, 1, [Define this symbol if stacktraces should be enabled]) +AM_CONDITIONAL([ENABLE_CRASH_HOOKS], [test x$enable_crashhooks = xyes]) +if test "x$enable_crashhooks" = xyes; then + AC_DEFINE(ENABLE_CRASH_HOOKS, 1, [Define this symbol if crash hooks should be enabled]) fi AX_CHECK_LINK_FLAG([-Wl,-wrap=__cxa_allocate_exception], [LINK_WRAP_SUPPORTED=yes],,,) -AX_CHECK_COMPILE_FLAG([-rdynamic], [RDYNAMIC_SUPPORTED=yes],,,) -AM_CONDITIONAL([STACKTRACE_WRAPPED_CXX_ABI],[test x$LINK_WRAP_SUPPORTED = xyes]) -AM_CONDITIONAL([RDYNAMIC_SUPPORTED],[test x$RDYNAMIC_SUPPORTED = xyes]) +AM_CONDITIONAL([CRASH_HOOKS_WRAPPED_CXX_ABI],[test x$LINK_WRAP_SUPPORTED = xyes]) if test x$LINK_WRAP_SUPPORTED = "xyes"; then - AC_DEFINE(STACKTRACE_WRAPPED_CXX_ABI, 1, [Define this symbol to use wrapped CXX ABIs for exception stacktraces])], + AC_DEFINE(CRASH_HOOKS_WRAPPED_CXX_ABI, 1, [Define this symbol to use wrapped CXX ABIs for exception stacktraces]) fi # Needed for MinGW targets when debug symbols are enabled as compiled objects get very large @@ -1142,6 +1142,18 @@ else AC_MSG_RESULT([no]) fi +# When compiled natively on MacOS, we need to specify -flat to avoid producing a dSYM bundle +# When cross-compiled on linux, we're using a different version of the tool that only supports flat symbol files +AC_MSG_CHECKING([whether dsymutil needs -flat]) +if test x$DSYMUTIL != x && ($DSYMUTIL --help | grep -q \\-flat); then +AC_MSG_RESULT([yes]) + DSYMUTIL_FLAT="$DSYMUTIL -flat" +else + AC_MSG_RESULT([no]) + DSYMUTIL_FLAT="$DSYMUTIL" +fi +AC_MSG_RESULT($dsymutil_needs_flat) + if test x$build_bitcoin_utils$build_bitcoin_libs$build_bitcoind$bitcoin_enable_qt$use_bench$use_tests = xnononononono; then AC_MSG_ERROR([No targets! Please specify at least one of: --with-utils --with-libs --with-daemon --with-gui --enable-bench or --enable-tests]) fi @@ -1205,6 +1217,7 @@ AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(ZMQ_LIBS) AC_SUBST(PROTOBUF_LIBS) AC_SUBST(QR_LIBS) +AC_SUBST(DSYMUTIL_FLAT) AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/functional/config.ini]) AC_CONFIG_FILES([test/util/buildenv.py],[chmod +x test/util/buildenv.py]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) @@ -1277,7 +1290,7 @@ echo " with test = $use_tests" echo " with bench = $use_bench" echo " with upnp = $use_upnp" echo " debug enabled = $enable_debug" -echo " stacktraces enabled = $enable_stacktraces" +echo " crash hooks enabled = $enable_crashhooks" echo " miner enabled = $enable_miner" echo " werror = $enable_werror" echo diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml index aa5508c1bad3..cc3166061acc 100755 --- a/contrib/gitian-descriptors/gitian-linux.yml +++ b/contrib/gitian-descriptors/gitian-linux.yml @@ -38,7 +38,7 @@ script: | WRAP_DIR=$HOME/wrapped HOSTS="i686-pc-linux-gnu x86_64-linux-gnu arm-linux-gnueabihf aarch64-linux-gnu" - CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests" + CONFIGFLAGS="--enable-glibc-back-compat --enable-reduce-exports --disable-bench --disable-gui-tests --enable-crash-hooks" FAKETIME_HOST_PROGS="" FAKETIME_PROGS="date ar ranlib nm" HOST_CFLAGS="-O2 -g" diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml index ab5b5d9b6877..cb241e3eeaec 100644 --- a/contrib/gitian-descriptors/gitian-osx.yml +++ b/contrib/gitian-descriptors/gitian-osx.yml @@ -37,7 +37,7 @@ files: script: | WRAP_DIR=$HOME/wrapped HOSTS="x86_64-apple-darwin11" - CONFIGFLAGS="--enable-reduce-exports --disable-miner --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage" + CONFIGFLAGS="--enable-reduce-exports --disable-miner --disable-bench --disable-gui-tests GENISOIMAGE=$WRAP_DIR/genisoimage --enable-crash-hooks" FAKETIME_HOST_PROGS="" FAKETIME_PROGS="ar ranlib date dmg genisoimage" @@ -146,6 +146,7 @@ script: | CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} make ${MAKEOPTS} + make -C src osx_debug make install-strip DESTDIR=${INSTALLPATH} make osx_volname @@ -170,12 +171,15 @@ script: | find . -name "lib*.la" -delete find . -name "lib*.a" -delete rm -rf ${DISTNAME}/lib/pkgconfig - find ${DISTNAME} | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz + find .. -name *.dSYM -exec cp -ra {} ${DISTNAME}/bin \; + find ${DISTNAME} -not -path '*.dSYM*' | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz + find ${DISTNAME} -path '*.dSYM*' | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz cd ../../ done mkdir -p $OUTDIR/src mv $SOURCEDIST $OUTDIR/src - mv ${OUTDIR}/${DISTNAME}-x86_64-*.tar.gz ${OUTDIR}/${DISTNAME}-osx64.tar.gz + mv ${OUTDIR}/${DISTNAME}-x86_64-apple-darwin11.tar.gz ${OUTDIR}/${DISTNAME}-osx64.tar.gz + mv ${OUTDIR}/${DISTNAME}-x86_64-apple-darwin11-debug.tar.gz ${OUTDIR}/${DISTNAME}-osx64-debug.tar.gz # Compress ccache (otherwise the assert file will get too huge) if [ "$CCACHE_DIR" != "" ]; then diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml index ff38be782abc..144a20a524fb 100755 --- a/contrib/gitian-descriptors/gitian-win.yml +++ b/contrib/gitian-descriptors/gitian-win.yml @@ -31,7 +31,7 @@ files: [] script: | WRAP_DIR=$HOME/wrapped HOSTS="i686-w64-mingw32 x86_64-w64-mingw32" - CONFIGFLAGS="--enable-reduce-exports --disable-miner --disable-bench --disable-gui-tests" + CONFIGFLAGS="--enable-reduce-exports --disable-miner --disable-bench --disable-gui-tests --enable-crash-hooks" FAKETIME_HOST_PROGS="ar ranlib nm windres strip objcopy" FAKETIME_PROGS="date makensis zip" HOST_CFLAGS="-O2 -g" diff --git a/src/Makefile.am b/src/Makefile.am index c3b2d83067b5..affd8bad4e9f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,8 +10,8 @@ AM_CXXFLAGS = $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) AM_CPPFLAGS = $(HARDENED_CPPFLAGS) EXTRA_LIBRARIES = -if ENABLE_STACKTRACES -if STACKTRACE_WRAPPED_CXX_ABI +if ENABLE_CRASH_HOOKS +if CRASH_HOOKS_WRAPPED_CXX_ABI # Wrap internal C++ ABI's so that we can attach stacktraces to exceptions LDFLAGS_WRAP_EXCEPTIONS = -Wl,-wrap,__cxa_allocate_exception -Wl,-wrap,__cxa_free_exception if TARGET_WINDOWS @@ -20,10 +20,6 @@ else LDFLAGS_WRAP_EXCEPTIONS += -Wl,-wrap,__assert_fail endif endif - -if RDYNAMIC_SUPPORTED -# This gives better stacktraces -AM_CXXFLAGS += -rdynamic endif if TARGET_WINDOWS @@ -31,7 +27,6 @@ BACKTRACE_LIB = -ldbghelp -lbacktrace else BACKTRACE_LIB = -lbacktrace endif -endif if EMBEDDED_UNIVALUE LIBUNIVALUE = univalue/libunivalue.la @@ -646,6 +641,7 @@ clean-local: -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno -rm -f config.h -rm -rf test/__pycache__ + -rm -rf *.dSYM test/*.dSYM bench/*.dSYM qt/*.dSYM qt/test/*.dSYM .rc.o: @test -f $(WINDRES) @@ -668,6 +664,10 @@ if HARDEN $(AM_V_at) READELF=$(READELF) OBJDUMP=$(OBJDUMP) $(top_srcdir)/contrib/devtools/security-check.py < $(bin_PROGRAMS) endif + +osx_debug: $(bin_PROGRAMS) + for i in $(bin_PROGRAMS); do mkdir -p $$i.dSYM/Contents/Resources/DWARF && $(DSYMUTIL_FLAT) -o $$i.dSYM/Contents/Resources/DWARF/$$(basename $$i) $$i &> /dev/null ; done + %.pb.cc %.pb.h: %.proto @test -f $(PROTOC) $(AM_V_GEN) $(PROTOC) --cpp_out=$(@D) --proto_path=$( +#if !__APPLE__ +#include +#endif #endif #if __APPLE__ #include +#include +#include +#include #endif -#ifdef ENABLE_STACKTRACES #include -#endif -#include // for basename() #include -static void PrintCrashInfo(const std::string& s) -{ - LogPrintf("%s", s); - fprintf(stderr, "%s", s.c_str()); - fflush(stderr); -} - std::string DemangleSymbol(const std::string& name) { #if __GNUC__ || __clang__ @@ -71,8 +70,7 @@ std::string DemangleSymbol(const std::string& name) // this is the case when the terminate handler or an assert already handled the exception static std::atomic skipAbortSignal(false); -#ifdef ENABLE_STACKTRACES -ssize_t GetExeFileNameImpl(char* buf, size_t bufSize) +static ssize_t GetExeFileNameImpl(char* buf, size_t bufSize) { #if WIN32 std::vector tmp(bufSize); @@ -101,7 +99,7 @@ ssize_t GetExeFileNameImpl(char* buf, size_t bufSize) #endif } -std::string GetExeFileName() +static std::string GetExeFileName() { std::vector buf(1024); while (true) { @@ -116,38 +114,51 @@ std::string GetExeFileName() } } +static std::string g_exeFileName = GetExeFileName(); +static std::string g_exeFileBaseName = fs::path(g_exeFileName).filename().string(); + static void my_backtrace_error_callback (void *data, const char *msg, int errnum) { - PrintCrashInfo(strprintf("libbacktrace error: %d - %s\n", errnum, msg)); } static backtrace_state* GetLibBacktraceState() { - static std::string exeFileName = GetExeFileName(); - static const char* exeFileNamePtr = exeFileName.empty() ? nullptr : exeFileName.c_str(); +#if WIN32 + // libbacktrace is not able to handle the DWARF debuglink in the .exe + // but luckily we can just specify the .dbg file here as it's a valid PE/XCOFF file + static std::string debugFileName = g_exeFileName + ".dbg"; + static const char* exeFileNamePtr = fs::exists(debugFileName) ? debugFileName.c_str() : g_exeFileName.c_str(); +#else + static const char* exeFileNamePtr = g_exeFileName.empty() ? nullptr : g_exeFileName.c_str(); +#endif static backtrace_state* st = backtrace_create_state(exeFileNamePtr, 1, my_backtrace_error_callback, NULL); return st; } #if WIN32 +static uint64_t GetBaseAddress() +{ + return 0; +} + // PC addresses returned by StackWalk64 are in the real mapped space, while libbacktrace expects them to be in the // default mapped space starting at 0x400000. This method converts the address. // TODO this is probably the same reason libbacktrace is not able to gather the stacktrace on Windows (returns pointers like 0x1 or 0xfffffff) // If they ever fix this problem, we might end up converting to invalid addresses here -static uintptr_t ConvertAddress(uintptr_t addr) +static uint64_t ConvertAddress(uint64_t addr) { MEMORY_BASIC_INFORMATION mbi; if (!VirtualQuery((PVOID)addr, &mbi, sizeof(mbi))) return 0; - uintptr_t hMod = (uintptr_t)mbi.AllocationBase; - uintptr_t offset = addr - hMod; + uint64_t hMod = (uint64_t)mbi.AllocationBase; + uint64_t offset = addr - hMod; return 0x400000 + offset; } -static __attribute__((noinline)) std::vector GetStackFrames(size_t skip, size_t max_frames, const CONTEXT* pContext = nullptr) +static __attribute__((noinline)) std::vector GetStackFrames(size_t skip, size_t max_frames, const CONTEXT* pContext = nullptr) { // We can't use libbacktrace for stack unwinding on Windows as it returns invalid addresses (like 0x1 or 0xffffffff) static BOOL symInitialized = SymInitialize(GetCurrentProcess(), NULL, TRUE); @@ -195,7 +206,7 @@ static __attribute__((noinline)) std::vector GetStackFrames(size_t sk #error unsupported architecture #endif - std::vector ret; + std::vector ret; size_t i = 0; while (ret.size() < max_frames) { @@ -208,7 +219,7 @@ static __attribute__((noinline)) std::vector GetStackFrames(size_t sk break; } if (i >= skip) { - uintptr_t pc = ConvertAddress(stackframe.AddrPC.Offset); + uint64_t pc = ConvertAddress(stackframe.AddrPC.Offset); if (pc == 0) { pc = stackframe.AddrPC.Offset; } @@ -220,18 +231,48 @@ static __attribute__((noinline)) std::vector GetStackFrames(size_t sk return ret; } #else -static int my_backtrace_simple_callback(void *data, uintptr_t pc) + +#if __APPLE__ +static uint64_t GetBaseAddress() +{ + mach_port_name_t target_task; + vm_map_offset_t vmoffset; + vm_map_size_t vmsize; + uint32_t nesting_depth = 0; + struct vm_region_submap_info_64 vbr; + mach_msg_type_number_t vbrcount = 16; + kern_return_t kr; + + kr = task_for_pid(mach_task_self(), getpid(), &target_task); + if (kr != KERN_SUCCESS) { + return 0; + } + + kr = mach_vm_region_recurse(target_task, &vmoffset, &vmsize, &nesting_depth, (vm_region_recurse_info_t)&vbr, &vbrcount); + if (kr != KERN_SUCCESS) { + return 0; + } + + return vmoffset; +} +#else +static int dl_iterate_callback(struct dl_phdr_info* info, size_t s, void* data) { - auto v = (std::vector*)data; - v->emplace_back(pc); - if (v->size() >= 128) { - // abort - return 1; + uint64_t* p = (uint64_t*)data; + if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0') { + *p = info->dlpi_addr; } - return 0; } -static __attribute__((noinline)) std::vector GetStackFrames(size_t skip, size_t max_frames) +static uint64_t GetBaseAddress() +{ + uint64_t basePtr = 0; + dl_iterate_phdr(dl_iterate_callback, &basePtr); + return basePtr; +} +#endif + +static __attribute__((noinline)) std::vector GetStackFrames(size_t skip, size_t max_frames) { // FYI, this is not using libbacktrace, but "backtrace()" from std::vector buf(max_frames); @@ -241,20 +282,31 @@ static __attribute__((noinline)) std::vector GetStackFrames(size_t sk } buf.resize((size_t)count); - std::vector ret; + std::vector ret; ret.reserve(count); for (size_t i = skip + 1; i < buf.size(); i++) { - ret.emplace_back((uintptr_t) buf[i]); + ret.emplace_back((uint64_t) buf[i]); } return ret; } #endif struct stackframe_info { - uintptr_t pc; + uint64_t pc{0}; std::string filename; - int lineno; + int lineno{-1}; std::string function; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(pc); + READWRITE(filename); + READWRITE(lineno); + READWRITE(function); + } }; static int my_backtrace_full_callback (void *data, uintptr_t pc, const char *filename, int lineno, const char *function) @@ -284,7 +336,7 @@ static int my_backtrace_full_callback (void *data, uintptr_t pc, const char *fil return 0; } -static std::vector GetStackFrameInfos(const std::vector& stackframes) +static std::vector GetStackFrameInfos(const std::vector& stackframes) { std::vector infos; infos.reserve(stackframes.size()); @@ -298,10 +350,124 @@ static std::vector GetStackFrameInfos(const std::vector& sis, size_t spaces = 2) +struct crash_info_header +{ + std::string magic; + uint16_t version; + std::string exeFileName; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(magic); + READWRITE(version); + READWRITE(exeFileName); + } +}; + +struct crash_info +{ + std::string crashDescription; + std::vector stackframes; + std::vector stackframeInfos; + + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) + { + READWRITE(crashDescription); + READWRITE(stackframes); + READWRITE(stackframeInfos); + } + + void ConvertAddresses(int64_t offset) + { + for (auto& sf : stackframes) { + sf += offset; + } + for (auto& sfi : stackframeInfos) { + sfi.pc += offset; + } + } +}; + +static std::string GetCrashInfoStrNoDebugInfo(crash_info ci) +{ + static uint64_t basePtr = GetBaseAddress(); + + CDataStream ds(SER_DISK, 0); + + crash_info_header hdr; + hdr.magic = "DashCrashInfo"; + hdr.version = 1; + hdr.exeFileName = g_exeFileBaseName; + ds << hdr; + + ci.ConvertAddresses(-(int64_t)basePtr); + ds << ci; + + auto ciStr = EncodeBase32((const unsigned char*)ds.data(), ds.size()); + std::string s = ci.crashDescription + "\n"; + s += strprintf("No debug information available for stacktrace. You should add debug information and then run:\n" + "%s -printcrashinfo=%s\n", g_exeFileBaseName, ciStr); + return s; +} + +static std::string GetCrashInfoStr(const crash_info& ci, size_t spaces = 2); + +std::string GetCrashInfoStrFromSerializedStr(const std::string& ciStr) { - if (sis.empty()) { - return "\n"; + static uint64_t basePtr = GetBaseAddress(); + + bool dataInvalid = false; + auto buf = DecodeBase32(ciStr.c_str(), &dataInvalid); + if (buf.empty() || dataInvalid) { + return "Error while deserializing crash info"; + } + + CDataStream ds(buf, SER_DISK, 0); + + crash_info_header hdr; + try { + ds >> hdr; + } catch (...) { + return "Error while deserializing crash info header"; + } + + if (hdr.magic != "DashCrashInfo") { + return "Invalid magic string"; + } + if (hdr.version != 1) { + return "Unsupported version"; + } + if (hdr.exeFileName != g_exeFileBaseName) { + return "Crash info is not for this executable"; + } + + crash_info ci; + try { + ds >> ci; + } catch (...) { + return "Error while deserializing crash info"; + } + + ci.ConvertAddresses(basePtr); + + if (ci.stackframeInfos.empty()) { + std::vector stackframes(ci.stackframes.begin(), ci.stackframes.end()); + ci.stackframeInfos = GetStackFrameInfos(stackframes); + } + + return GetCrashInfoStr(ci); +} + +static std::string GetCrashInfoStr(const crash_info& ci, size_t spaces) +{ + if (ci.stackframeInfos.empty()) { + return GetCrashInfoStrNoDebugInfo(ci); } std::string sp; @@ -310,16 +476,14 @@ static std::string GetStackFrameInfosStr(const std::vector& sis } std::vector lstrs; - lstrs.reserve(sis.size()); + lstrs.reserve(ci.stackframeInfos.size()); - for (size_t i = 0; i < sis.size(); i++) { - auto& si = sis[i]; + for (size_t i = 0; i < ci.stackframeInfos.size(); i++) { + auto& si = ci.stackframeInfos[i]; std::string lstr; if (!si.filename.empty()) { - std::vector vecFilename(si.filename.size() + 1, '\0'); - strcpy(vecFilename.data(), si.filename.c_str()); - lstr += basename(vecFilename.data()); + lstr += fs::path(si.filename).filename().string(); } else { lstr += ""; } @@ -335,9 +499,9 @@ static std::string GetStackFrameInfosStr(const std::vector& sis std::string fmtStr = strprintf("%%2d#: (0x%%08X) %%-%ds - %%s\n", lstrlen); - std::string s; - for (size_t i = 0; i < sis.size(); i++) { - auto& si = sis[i]; + std::string s = ci.crashDescription + "\n"; + for (size_t i = 0; i < ci.stackframeInfos.size(); i++) { + auto& si = ci.stackframeInfos[i]; auto& lstr = lstrs[i]; @@ -356,10 +520,19 @@ static std::string GetStackFrameInfosStr(const std::vector& sis return s; } +static void PrintCrashInfo(const crash_info& ci) +{ + auto str = GetCrashInfoStr(ci); + LogPrintf("%s", str); + fprintf(stderr, "%s", str.c_str()); + fflush(stderr); +} + +#ifdef ENABLE_CRASH_HOOKS static std::mutex g_stacktraces_mutex; -static std::map>> g_stacktraces; +static std::map>> g_stacktraces; -#if STACKTRACE_WRAPPED_CXX_ABI +#if CRASH_HOOKS_WRAPPED_CXX_ABI // These come in through -Wl,-wrap // It only works on GCC extern "C" void* __real___cxa_allocate_exception(size_t thrown_size); @@ -402,7 +575,7 @@ extern "C" void __real___assert_fail(const char *assertion, const char *file, un #endif #endif -#if STACKTRACE_WRAPPED_CXX_ABI +#if CRASH_HOOKS_WRAPPED_CXX_ABI #define WRAPPED_NAME(x) __wrap_##x #else #define WRAPPED_NAME(x) x @@ -415,7 +588,7 @@ extern "C" void* __attribute__((noinline)) WRAPPED_NAME(__cxa_allocate_exception // WARNING keep this as it is and don't try to optimize it (no std::move, no std::make_shared, ...) // trying to optimize this will cause the optimizer to move the GetStackFrames() call deep into the stl libs - std::shared_ptr> st(new std::vector(localSt)); + std::shared_ptr> st(new std::vector(localSt)); void* p = __real___cxa_allocate_exception(thrown_size); @@ -432,41 +605,64 @@ extern "C" void __attribute__((noinline)) WRAPPED_NAME(__cxa_free_exception)(voi g_stacktraces.erase(thrown_exception); } +static __attribute__((noinline)) crash_info GetCrashInfoFromAssertion(const char* assertion, const char* file, int line, const char* function) +{ + crash_info ci; + ci.stackframes = GetStackFrames(1, 16); + ci.crashDescription = "Assertion failure:"; + if (assertion) { + ci.crashDescription += strprintf("\n assertion: %s", assertion); + } + if (file) { + ci.crashDescription += strprintf("\n file: %s, line: %d", file, line); + } + if (function) { + ci.crashDescription += strprintf("\n function: %s", function); + } + ci.stackframeInfos = GetStackFrameInfos(ci.stackframes); + return ci; +} + #if __clang__ extern "C" void __attribute__((noinline)) WRAPPED_NAME(__assert_rtn)(const char *function, const char *file, int line, const char *assertion) { - auto st = GetCurrentStacktraceStr(1); - PrintCrashInfo(strprintf("#### assertion failed: %s ####\n%s", assertion, st)); + auto ci = GetCrashInfoFromAssertion(assertion, file, line, function); + PrintCrashInfo(ci); skipAbortSignal = true; __real___assert_rtn(function, file, line, assertion); } #elif WIN32 extern "C" void __attribute__((noinline)) WRAPPED_NAME(_assert)(const char *assertion, const char *file, unsigned int line) { - auto st = GetCurrentStacktraceStr(1); - PrintCrashInfo(strprintf("#### assertion failed: %s ####\n%s", assertion, st)); + auto ci = GetCrashInfoFromAssertion(assertion, file, line, nullptr); + PrintCrashInfo(ci); skipAbortSignal = true; __real__assert(assertion, file, line); } extern "C" void __attribute__((noinline)) WRAPPED_NAME(_wassert)(const wchar_t *assertion, const wchar_t *file, unsigned int line) { - auto st = GetCurrentStacktraceStr(1); - PrintCrashInfo(strprintf("#### assertion failed: %s ####\n%s", std::string(assertion, assertion + wcslen(assertion)), st)); + auto ci = GetCrashInfoFromAssertion( + assertion ? std::string(assertion, assertion + wcslen(assertion)).c_str() : nullptr, + file ? std::string(file, file + wcslen(file)).c_str() : nullptr, + line, nullptr); + PrintCrashInfo(ci); skipAbortSignal = true; __real__wassert(assertion, file, line); } #else extern "C" void __attribute__((noinline)) WRAPPED_NAME(__assert_fail)(const char *assertion, const char *file, unsigned int line, const char *function) { - auto st = GetCurrentStacktraceStr(1); - PrintCrashInfo(strprintf("#### assertion failed: %s ####\n%s", assertion, st)); + auto ci = GetCrashInfoFromAssertion(assertion, file, line, function); + PrintCrashInfo(ci); skipAbortSignal = true; __real___assert_fail(assertion, file, line, function); } #endif +#endif //ENABLE_CRASH_HOOKS -static std::shared_ptr> GetExceptionStacktrace(const std::exception_ptr& e) +static std::shared_ptr> GetExceptionStacktrace(const std::exception_ptr& e) { +#ifdef ENABLE_CRASH_HOOKS void* p = *(void**)&e; std::lock_guard l(g_stacktraces_mutex); @@ -475,36 +671,19 @@ static std::shared_ptr> GetExceptionStacktrace(const std: return nullptr; } return it->second; -} -#endif //ENABLE_STACKTRACES - -std::string GetExceptionStacktraceStr(const std::exception_ptr& e) -{ -#ifdef ENABLE_STACKTRACES - auto stackframes = GetExceptionStacktrace(e); - if (stackframes && !stackframes->empty()) { - auto infos = GetStackFrameInfos(*stackframes); - return GetStackFrameInfosStr(infos); - } -#endif - return "\n"; -} - -std::string __attribute__((noinline)) GetCurrentStacktraceStr(size_t skip, size_t max_depth) -{ -#ifdef ENABLE_STACKTRACES - auto stackframes = GetStackFrames(skip + 1, max_depth); // +1 to skip current method - auto infos = GetStackFrameInfos(stackframes); - return GetStackFrameInfosStr(infos); #else - return "\n"; + return {}; #endif } -std::string GetPrettyExceptionStr(const std::exception_ptr& e) +crash_info GetCrashInfoFromException(const std::exception_ptr& e) { + crash_info ci; + ci.crashDescription = "Exception: "; + if (!e) { - return "\n"; + ci.crashDescription += ""; + return ci; } std::string type; @@ -536,35 +715,42 @@ std::string GetPrettyExceptionStr(const std::exception_ptr& e) type = DemangleSymbol(type); } - std::string s = strprintf("Exception: type=%s, what=\"%s\"\n", type, what); + ci.crashDescription += strprintf("type=%s, what=\"%s\"", type, what); -#if ENABLE_STACKTRACES - s += GetExceptionStacktraceStr(e); -#endif + auto stackframes = GetExceptionStacktrace(e); + if (stackframes) { + ci.stackframes = *stackframes; + ci.stackframeInfos = GetStackFrameInfos(ci.stackframes); + } - return s; + return ci; +} + +std::string GetPrettyExceptionStr(const std::exception_ptr& e) +{ + return GetCrashInfoStr(GetCrashInfoFromException(e)); } static void terminate_handler() { auto exc = std::current_exception(); - std::string s, s2; - s += "#### std::terminate() called, aborting ####\n"; + crash_info ci; + ci.crashDescription = "std::terminate() called, aborting"; if (exc) { - s += "#### UNCAUGHT EXCEPTION ####\n"; - s2 = GetPrettyExceptionStr(exc); + auto ci2 = GetCrashInfoFromException(exc); + ci.crashDescription = strprintf("std::terminate() called due to unhandled exception\n%s", ci2.crashDescription); + ci.stackframes = std::move(ci2.stackframes); + ci.stackframeInfos = std::move(ci2.stackframeInfos); } else { - s += "#### UNKNOWN REASON ####\n"; -#ifdef ENABLE_STACKTRACES - s2 = GetCurrentStacktraceStr(0); -#else - s2 = "\n"; -#endif + ci.crashDescription = "std::terminate() called due unknown reason"; + ci.stackframes = GetStackFrames(0, 16); } - PrintCrashInfo(strprintf("%s%s", s, s2)); + ci.stackframeInfos = GetStackFrameInfos(ci.stackframes); + + PrintCrashInfo(ci); skipAbortSignal = true; std::abort(); @@ -575,25 +761,28 @@ void RegisterPrettyTerminateHander() std::set_terminate(terminate_handler); } -#ifdef ENABLE_STACKTRACES #if !WIN32 static void HandlePosixSignal(int s) { if (s == SIGABRT && skipAbortSignal) { return; } - std::string st = GetCurrentStacktraceStr(0); + const char* name = strsignal(s); if (!name) { name = "UNKNOWN"; } - PrintCrashInfo(strprintf("#### signal %s ####\n%s", name, st)); + + crash_info ci; + ci.crashDescription = strprintf("Posix Signal: %s", name); + ci.stackframes = GetStackFrames(0, 16); + ci.stackframeInfos = GetStackFrameInfos(ci.stackframes); + PrintCrashInfo(ci); // avoid a signal loop skipAbortSignal = true; std::abort(); } - #else static void DoHandleWindowsException(EXCEPTION_POINTERS * ExceptionInfo) { @@ -623,11 +812,12 @@ static void DoHandleWindowsException(EXCEPTION_POINTERS * ExceptionInfo) default: excType = "UNKNOWN"; break; } - auto stackframes = GetStackFrames(0, 16, ExceptionInfo->ContextRecord); - auto infos = GetStackFrameInfos(stackframes); - auto infosStr = GetStackFrameInfosStr(infos); + crash_info ci; + ci.crashDescription = strprintf("Windows Exception: %s", excType); + ci.stackframes = GetStackFrames(0, 16, ExceptionInfo->ContextRecord); + ci.stackframeInfos = GetStackFrameInfos(ci.stackframes); - PrintCrashInfo(strprintf("#### Windows Exception %s ####\n%s", excType, infosStr)); + PrintCrashInfo(ci); } LONG WINAPI HandleWindowsException(EXCEPTION_POINTERS * ExceptionInfo) @@ -645,11 +835,9 @@ LONG WINAPI HandleWindowsException(EXCEPTION_POINTERS * ExceptionInfo) return EXCEPTION_CONTINUE_SEARCH; } #endif -#endif // ENABLE_STACKTRACES void RegisterPrettySignalHandlers() { -#if ENABLE_STACKTRACES #if WIN32 SetUnhandledExceptionFilter(HandleWindowsException); #else @@ -679,5 +867,4 @@ void RegisterPrettySignalHandlers() sigaction(s, &sa_segv, NULL); } #endif -#endif } diff --git a/src/stacktraces.h b/src/stacktraces.h index 152c7699ddad..11ee85f2b2a4 100644 --- a/src/stacktraces.h +++ b/src/stacktraces.h @@ -15,10 +15,8 @@ std::string DemangleSymbol(const std::string& name); -std::string GetCurrentStacktraceStr(size_t skip = 0, size_t max_depth = 16); - -std::string GetExceptionStacktraceStr(const std::exception_ptr& e); std::string GetPrettyExceptionStr(const std::exception_ptr& e); +std::string GetCrashInfoStrFromSerializedStr(const std::string& ciStr); template std::string GetExceptionWhat(const T& e); diff --git a/src/util.cpp b/src/util.cpp index 9ce303b05705..5001af45c6b2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -602,7 +602,7 @@ std::string HelpMessageOpt(const std::string &option, const std::string &message static std::string FormatException(const std::exception_ptr pex, const char* pszThread) { - return strprintf("EXCEPTION: %s", GetPrettyExceptionStr(pex)); + return GetPrettyExceptionStr(pex); } void PrintExceptionContinue(const std::exception_ptr pex, const char* pszThread) From b9aadc071b19ea4e92b62b2db99e9fe54d9d74fc Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 2 Jul 2019 06:16:27 +0200 Subject: [PATCH 327/987] Fix excessive memory use when flushing chainstate and EvoDB (#3008) * Specialize Serialize(CSizeComputer&) for BLS objects Speeds up size computation for BLS objects. * Track memory usage in CDBTransaction and CEvoDB * Take memory used by CEvoDB/CDBTransaction into account when flushing * Implement specialized SerReadWrite for immer maps This allows to use READWRITE and fixes compilation errors with CSizeComputer * Log EvoDB memory usage independently Co-Authored-By: UdjinM6 --- src/bls/bls.h | 10 +++++++++ src/dbwrapper.h | 42 +++++++++++++++++++++++++++++++++----- src/evo/deterministicmns.h | 24 +++++++++++++++------- src/evo/evodb.h | 5 +++++ src/validation.cpp | 2 ++ 5 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/bls/bls.h b/src/bls/bls.h index 4d5881f4c659..f375dcf00c88 100644 --- a/src/bls/bls.h +++ b/src/bls/bls.h @@ -170,6 +170,11 @@ class CBLSWrapper } public: + inline void Serialize(CSizeComputer& s) const + { + s.seek(SerSize); + } + template inline void Serialize(Stream& s) const { @@ -356,6 +361,11 @@ class CBLSLazyWrapper return *this; } + inline void Serialize(CSizeComputer& s) const + { + s.seek(BLSObject::SerSize); + } + template inline void Serialize(Stream& s) const { diff --git a/src/dbwrapper.h b/src/dbwrapper.h index 7033b2b2539f..a20998f7fe71 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -550,6 +550,7 @@ class CDBTransaction { protected: Parent &parent; CommitTarget &commitTarget; + ssize_t memoryUsage{0}; // signed, just in case we made an error in the calculations so that we don't get an overflow struct DataStreamCmp { static bool less(const CDataStream& a, const CDataStream& b) { @@ -563,6 +564,8 @@ class CDBTransaction { }; struct ValueHolder { + size_t memoryUsage; + ValueHolder(size_t _memoryUsage) : memoryUsage(_memoryUsage) {} virtual ~ValueHolder() = default; virtual void Write(const CDataStream& ssKey, CommitTarget &parent) = 0; }; @@ -570,7 +573,7 @@ class CDBTransaction { template struct ValueHolderImpl : ValueHolder { - ValueHolderImpl(const V &_value) : value(_value) { } + ValueHolderImpl(const V &_value, size_t _memoryUsage) : ValueHolder(_memoryUsage), value(_value) {} virtual void Write(const CDataStream& ssKey, CommitTarget &commitTarget) { // we're moving the value instead of copying it. This means that Write() can only be called once per @@ -604,9 +607,18 @@ class CDBTransaction { template void Write(const CDataStream& ssKey, const V& v) { - deletes.erase(ssKey); + auto valueMemoryUsage = ::GetSerializeSize(v, SER_DISK, CLIENT_VERSION); + + if (deletes.erase(ssKey)) { + memoryUsage -= ssKey.size(); + } auto it = writes.emplace(ssKey, nullptr).first; - it->second = std::make_unique>(v); + if (it->second) { + memoryUsage -= ssKey.size() + it->second->memoryUsage; + } + it->second = std::make_unique>(v, valueMemoryUsage); + + memoryUsage += ssKey.size() + valueMemoryUsage; } template @@ -656,13 +668,20 @@ class CDBTransaction { } void Erase(const CDataStream& ssKey) { - writes.erase(ssKey); - deletes.emplace(ssKey); + auto it = writes.find(ssKey); + if (it != writes.end()) { + memoryUsage -= ssKey.size() + it->second->memoryUsage; + writes.erase(it); + } + if (deletes.emplace(ssKey).second) { + memoryUsage += ssKey.size(); + } } void Clear() { writes.clear(); deletes.clear(); + memoryUsage = 0; } void Commit() { @@ -679,6 +698,19 @@ class CDBTransaction { return writes.empty() && deletes.empty(); } + size_t GetMemoryUsage() const { + if (memoryUsage < 0) { + // something went wrong when we accounted/calculated used memory... + static volatile bool didPrint = false; + if (!didPrint) { + LogPrintf("CDBTransaction::%s -- negative memoryUsage (%d)", __func__, memoryUsage); + didPrint = true; + } + return 0; + } + return (size_t)memoryUsage; + } + CDBTransactionIterator* NewIterator() { return new CDBTransactionIterator(*this); } diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index 6ddc32a399d7..a917e95b34e3 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -195,6 +195,21 @@ void UnserializeImmerMap(Stream& is, immer::map& m) } } +// For some reason the compiler is not able to choose the correct Serialize/Deserialize methods without a specialized +// version of SerReadWrite. It otherwise always chooses the version that calls a.Serialize() +template +inline void SerReadWrite(Stream& s, const immer::map& m, CSerActionSerialize ser_action) +{ + ::SerializeImmerMap(s, m); +} + +template +inline void SerReadWrite(Stream& s, immer::map& obj, CSerActionUnserialize ser_action) +{ + ::UnserializeImmerMap(s, obj); +} + + class CDeterministicMNList { public: @@ -226,13 +241,8 @@ class CDeterministicMNList { READWRITE(blockHash); READWRITE(nHeight); - if (ser_action.ForRead()) { - UnserializeImmerMap(s, mnMap); - UnserializeImmerMap(s, mnUniquePropertyMap); - } else { - SerializeImmerMap(s, mnMap); - SerializeImmerMap(s, mnUniquePropertyMap); - } + READWRITE(mnMap); + READWRITE(mnUniquePropertyMap); } public: diff --git a/src/evo/evodb.h b/src/evo/evodb.h index dbc8d64ba689..7772f6b06310 100644 --- a/src/evo/evodb.h +++ b/src/evo/evodb.h @@ -73,6 +73,11 @@ class CEvoDB return db; } + size_t GetMemoryUsage() + { + return rootDBTransaction.GetMemoryUsage(); + } + bool CommitRootTransaction(); bool VerifyBestBlock(const uint256& hash); diff --git a/src/validation.cpp b/src/validation.cpp index effaff2d7b0d..56c8319abdd7 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2423,6 +2423,7 @@ bool static FlushStateToDisk(const CChainParams& chainparams, CValidationState & } int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; int64_t cacheSize = pcoinsTip->DynamicMemoryUsage() * DB_PEAK_USAGE_FACTOR; + cacheSize += evoDb->GetMemoryUsage() * DB_PEAK_USAGE_FACTOR; int64_t nTotalSpace = nCoinCacheUsage + std::max(nMempoolSizeMax - nMempoolUsage, 0); // The cache is large and we're within 10% and 10 MiB of the limit, but we have time now (not in the middle of a block processing). bool fCacheLarge = mode == FLUSH_STATE_PERIODIC && cacheSize > std::max((9 * nTotalSpace) / 10, nTotalSpace - MAX_BLOCK_COINSDB_USAGE * 1024 * 1024); @@ -2563,6 +2564,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); + strMessage += strprintf(" evodb_cache=%.1fMiB", evoDb->GetMemoryUsage() * (1.0 / (1<<20))); if (!warningMessages.empty()) strMessage += strprintf(" warning='%s'", boost::algorithm::join(warningMessages, ", ")); LogPrintf("%s\n", strMessage); From 4968710a2fed92c86ae4d2aa31a240bc0fc87f69 Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 2 Jul 2019 00:38:07 -0500 Subject: [PATCH 328/987] Resolve AvailableCoins method call --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index bad6e3d442c8..d6357557296d 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3476,7 +3476,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT LOCK2(cs_main, cs_wallet); { std::vector vAvailableCoins; - AvailableCoins(vAvailableCoins, true, coinControl, 0, MAX_MONEY, MAX_MONEY, 0, false, nCoinType, fUseInstantSend); + AvailableCoins(vAvailableCoins, true, coinControl, 0, MAX_MONEY, MAX_MONEY, 0, nCoinType, fUseInstantSend); int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired; nFeeRet = 0; From 9e2235a4bc86b5e3de89655c5d2f948630e404c4 Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 2 Jul 2019 10:34:23 -0500 Subject: [PATCH 329/987] add initializing to regtest Signed-off-by: Pasta --- src/chainparams.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 7d605c32ea6f..99de1bd92229 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -809,6 +809,8 @@ class CRegTestParams : public CChainParams { fAllowMultiplePorts = true; nFulfilledRequestExpireTime = 5*60; // fulfilled requests expire in 5 minutes + nPoolMinParticipants = 3; + nPoolMaxParticipants = 5; // privKey: cP4EKFyJsHT39LDqgdcB43Y3YXjNyjb5Fuas1GQSeAtjnZWmZEQK vSporkAddresses = {"yj949n1UH6fDhw6HtVE5VMj2iSTaSWBMcW"}; From 1bbe050fe021919fe1ec6213f7f5446fa93ddaca Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 2 Jul 2019 10:38:11 -0500 Subject: [PATCH 330/987] adjust check || -> && Signed-off-by: Pasta --- src/wallet/wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d6357557296d..a41b3be57270 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2602,7 +2602,7 @@ void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs && !coinControl->IsSelected(COutPoint((*it).first, i))) continue; - if (IsLockedCoin((*it).first, i) || nCoinType != ONLY_1000) + if (IsLockedCoin((*it).first, i) && nCoinType != ONLY_1000) continue; if (IsSpent(wtxid, i)) From c6eededcabc8fcbf730c3dc050ba4ad135177804 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 2 Jul 2019 22:44:29 +0200 Subject: [PATCH 331/987] Add "isValidMember" and "memberIndex" to "quorum memberof" and allow to specify quorum scan count (#3009) * Add "isValidMember" and "memberIndex" to output of "quorum memberof" * Allow to specify how many quorums to scan for in "quorum memberof" --- src/rpc/rpcquorums.cpp | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/rpc/rpcquorums.cpp b/src/rpc/rpcquorums.cpp index 4cfd5caf24a8..b9709ef8c902 100644 --- a/src/rpc/rpcquorums.cpp +++ b/src/rpc/rpcquorums.cpp @@ -192,20 +192,29 @@ UniValue quorum_dkgstatus(const JSONRPCRequest& request) void quorum_memberof_help() { throw std::runtime_error( - "quorum memberof \"proTxHash\"\n" + "quorum memberof \"proTxHash\" (quorumCount)\n" "Checks which quorums the given masternode is a member of.\n" "\nArguments:\n" "1. \"proTxHash\" (string, required) ProTxHash of the masternode.\n" + "2. scanQuorumsCount (number, optional) Number of quorums to scan for. If not specified,\n" + " the active quorum count for each specific quorum type is used." ); } UniValue quorum_memberof(const JSONRPCRequest& request) { - if (request.fHelp || (request.params.size() != 2)) { + if (request.fHelp || (request.params.size() < 2 || request.params.size() > 3)) { quorum_memberof_help(); } uint256 protxHash = ParseHashV(request.params[1], "proTxHash"); + int scanQuorumsCount = -1; + if (request.params.size() >= 3) { + scanQuorumsCount = ParseInt32V(request.params[2], "scanQuorumsCount"); + if (scanQuorumsCount <= 0) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid scanQuorumsCount parameter"); + } + } const CBlockIndex* pindexTip; { @@ -219,26 +228,25 @@ UniValue quorum_memberof(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "masternode not found"); } - std::set> quorumHashes; + UniValue result(UniValue::VARR); + for (const auto& p : Params().GetConsensus().llmqs) { auto& params = p.second; - auto quorums = llmq::quorumManager->ScanQuorums(params.type, params.signingActiveQuorumCount); + size_t count = params.signingActiveQuorumCount; + if (scanQuorumsCount != -1) { + count = (size_t)scanQuorumsCount; + } + auto quorums = llmq::quorumManager->ScanQuorums(params.type, count); for (auto& quorum : quorums) { - for (auto& m : quorum->members) { - if (m->proTxHash == dmn->proTxHash) { - quorumHashes.emplace(params.type, quorum->qc.quorumHash); - } + if (quorum->IsMember(dmn->proTxHash)) { + auto json = BuildQuorumInfo(quorum, false, false); + json.push_back(Pair("isValidMember", quorum->IsValidMember(dmn->proTxHash))); + json.push_back(Pair("memberIndex", quorum->GetMemberIndex(dmn->proTxHash))); + result.push_back(json); } } } - UniValue result(UniValue::VARR); - for (auto& p : quorumHashes) { - auto quorum = llmq::quorumManager->GetQuorum(p.first, p.second); - assert(quorum); - result.push_back(BuildQuorumInfo(quorum, false, false)); - } - return result; } From b401a3baa90d29d9e6e6a50a9242ec9775938fa3 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Tue, 2 Jul 2019 23:45:33 +0300 Subject: [PATCH 332/987] Fix compilation on Ubuntu 16.04 (#3013) --- depends/packages/backtrace.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depends/packages/backtrace.mk b/depends/packages/backtrace.mk index d84391c0fef8..c7e47c788d32 100644 --- a/depends/packages/backtrace.mk +++ b/depends/packages/backtrace.mk @@ -5,7 +5,7 @@ $(package)_file_name=$($(package)_version).tar.gz $(package)_sha256_hash=8da6daa0a582c9bbd1f2933501168b4c43664700f604f43e922e85b99e5049bc define $(package)_set_vars -$(package)_config_opts=--disable-shared --prefix=$(host_prefix) +$(package)_config_opts=--disable-shared --enable-host-shared --prefix=$(host_prefix) endef define $(package)_config_cmds From ee9adb94823f11f21a8445ba186337d496b56178 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 2 Jul 2019 22:46:03 +0200 Subject: [PATCH 333/987] Use std::unique_ptr for mnList in CSimplifiedMNList (#3014) This allows much faster sorting as it avoids copying/swapping expensive objects. --- src/evo/simplifiedmns.cpp | 22 +++++++++++++--------- src/evo/simplifiedmns.h | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index d23e0f9ce7d6..10c0d59b4c84 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -54,23 +54,27 @@ void CSimplifiedMNListEntry::ToJson(UniValue& obj) const CSimplifiedMNList::CSimplifiedMNList(const std::vector& smlEntries) { - mnList = smlEntries; + mnList.resize(smlEntries.size()); + for (size_t i = 0; i < smlEntries.size(); i++) { + mnList[i] = std::make_unique(smlEntries[i]); + } - std::sort(mnList.begin(), mnList.end(), [&](const CSimplifiedMNListEntry& a, const CSimplifiedMNListEntry& b) { - return a.proRegTxHash.Compare(b.proRegTxHash) < 0; + std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->proRegTxHash.Compare(b->proRegTxHash) < 0; }); } CSimplifiedMNList::CSimplifiedMNList(const CDeterministicMNList& dmnList) { - mnList.reserve(dmnList.GetAllMNsCount()); + mnList.resize(dmnList.GetAllMNsCount()); - dmnList.ForEachMN(false, [this](const CDeterministicMNCPtr& dmn) { - mnList.emplace_back(*dmn); + size_t i = 0; + dmnList.ForEachMN(false, [this, &i](const CDeterministicMNCPtr& dmn) { + mnList[i++] = std::make_unique(*dmn); }); - std::sort(mnList.begin(), mnList.end(), [&](const CSimplifiedMNListEntry& a, const CSimplifiedMNListEntry& b) { - return a.proRegTxHash.Compare(b.proRegTxHash) < 0; + std::sort(mnList.begin(), mnList.end(), [&](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->proRegTxHash.Compare(b->proRegTxHash) < 0; }); } @@ -79,7 +83,7 @@ uint256 CSimplifiedMNList::CalcMerkleRoot(bool* pmutated) const std::vector leaves; leaves.reserve(mnList.size()); for (const auto& e : mnList) { - leaves.emplace_back(e.CalcHash()); + leaves.emplace_back(e->CalcHash()); } return ComputeMerkleRoot(leaves, pmutated); } diff --git a/src/evo/simplifiedmns.h b/src/evo/simplifiedmns.h index 7a642b29af76..8a66f428f4cd 100644 --- a/src/evo/simplifiedmns.h +++ b/src/evo/simplifiedmns.h @@ -74,7 +74,7 @@ class CSimplifiedMNListEntry class CSimplifiedMNList { public: - std::vector mnList; + std::vector> mnList; public: CSimplifiedMNList() {} From a685391c77a21bcd0b76bf8d765d2d591ddae657 Mon Sep 17 00:00:00 2001 From: Pasta Date: Tue, 2 Jul 2019 10:53:47 -0500 Subject: [PATCH 334/987] fix AvailableCoins Calls Signed-off-by: Pasta --- src/rpc/masternode.cpp | 2 +- src/wallet/wallet.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 80102a71f7f0..087ccd12742a 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -320,7 +320,7 @@ UniValue masternode_outputs(const JSONRPCRequest& request) // Find possible candidates std::vector vPossibleCoins; - pwallet->AvailableCoins(vPossibleCoins, true, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_1000); + pwallet->AvailableCoins(vPossibleCoins, true, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_1000); UniValue obj(UniValue::VOBJ); for (const auto& out : vPossibleCoins) { diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a41b3be57270..41b7e227e305 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3041,7 +3041,7 @@ bool CWallet::SelectPSInOutPairsByDenominations(int nDenom, CAmount nValueMin, C return false; } - AvailableCoins(vCoins, true, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_DENOMINATED); + AvailableCoins(vCoins, true, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_DENOMINATED, false); LogPrintf("CWallet::%s -- vCoins.size(): %d\n", __func__, vCoins.size()); std::random_shuffle(vCoins.rbegin(), vCoins.rend(), GetRandInt); @@ -3183,7 +3183,7 @@ bool CWallet::SelectPrivateCoins(CAmount nValueMin, CAmount nValueMax, std::vect nValueRet = 0; std::vector vCoins; - AvailableCoins(vCoins, true, coinControl, 0, MAX_MONEY, MAX_MONEY, 0, false, nPrivateSendRoundsMin < 0 ? ONLY_NONDENOMINATED : ONLY_DENOMINATED); + AvailableCoins(vCoins, true, coinControl, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, nPrivateSendRoundsMin < 0 ? ONLY_NONDENOMINATED : ONLY_DENOMINATED); //order the array so largest nondenom are first, then denominations, then very small inputs. std::sort(vCoins.rbegin(), vCoins.rend(), CompareByPriority()); @@ -3217,7 +3217,7 @@ bool CWallet::GetCollateralTxDSIn(CTxDSIn& txdsinRet, CAmount& nValueRet) const std::vector vCoins; - AvailableCoins(vCoins, true, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_PRIVATESEND_COLLATERAL); + AvailableCoins(vCoins, true, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_PRIVATESEND_COLLATERAL); if (vCoins.empty()) { return false; @@ -3236,7 +3236,7 @@ bool CWallet::GetMasternodeOutpointAndKeys(COutPoint& outpointRet, CPubKey& pubK // Find possible candidates std::vector vPossibleCoins; - AvailableCoins(vPossibleCoins, true, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_1000); + AvailableCoins(vPossibleCoins, true, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_1000); if(vPossibleCoins.empty()) { LogPrintf("CWallet::GetMasternodeOutpointAndKeys -- Could not locate any valid masternode vin\n"); return false; @@ -3307,7 +3307,7 @@ int CWallet::CountInputsWithAmount(CAmount nInputAmount) const bool CWallet::HasCollateralInputs(bool fOnlyConfirmed) const { std::vector vCoins; - AvailableCoins(vCoins, fOnlyConfirmed, NULL, 0, MAX_MONEY, MAX_MONEY, 0, false, ONLY_PRIVATESEND_COLLATERAL); + AvailableCoins(vCoins, fOnlyConfirmed, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_PRIVATESEND_COLLATERAL); return !vCoins.empty(); } @@ -3476,7 +3476,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT LOCK2(cs_main, cs_wallet); { std::vector vAvailableCoins; - AvailableCoins(vAvailableCoins, true, coinControl, 0, MAX_MONEY, MAX_MONEY, 0, nCoinType, fUseInstantSend); + AvailableCoins(vAvailableCoins, true, coinControl, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, nCoinType, fUseInstantSend); int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired; nFeeRet = 0; From 46dd6a357564301c29c3aecedb404271378d09ad Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 3 Jul 2019 17:07:07 -0500 Subject: [PATCH 335/987] make mainnetDefaultPort static Signed-off-by: Pasta --- src/evo/providertx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp index f4cec8262055..2dca75bc6230 100644 --- a/src/evo/providertx.cpp +++ b/src/evo/providertx.cpp @@ -27,7 +27,7 @@ static bool CheckService(const uint256& proTxHash, const ProTx& proTx, CValidati return state.DoS(10, false, REJECT_INVALID, "bad-protx-addr"); } - int mainnetDefaultPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPort(); + static int mainnetDefaultPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPort(); if (Params().NetworkIDString() == CBaseChainParams::MAIN) { if (proTx.addr.GetPort() != mainnetDefaultPort) { return state.DoS(10, false, REJECT_INVALID, "bad-protx-addr-port"); From 3c96b2526268a9bc0840d7a3b1f86370f2bd9334 Mon Sep 17 00:00:00 2001 From: Pasta Date: Thu, 4 Jul 2019 22:59:48 -0500 Subject: [PATCH 336/987] stop_node(s) -> self.stop_node(s) in dash specific tests Signed-off-by: Pasta --- test/functional/dip3-deterministicmns.py | 2 +- test/functional/fundrawtransaction-hd.py | 6 +++--- test/functional/llmq-chainlocks.py | 2 +- test/functional/sporks.py | 4 ++-- test/functional/test_framework/test_framework.py | 2 +- test/functional/wallet-hd.py | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/functional/dip3-deterministicmns.py b/test/functional/dip3-deterministicmns.py index 65421ce54ed1..c5d98267cbe3 100755 --- a/test/functional/dip3-deterministicmns.py +++ b/test/functional/dip3-deterministicmns.py @@ -45,7 +45,7 @@ def start_controller_node(self, extra_args=None): def stop_controller_node(self): self.log.info("stopping controller node") - stop_node(self.nodes[0], 0) + self.stop_node(self.nodes[0], 0) def restart_controller_node(self): self.stop_controller_node() diff --git a/test/functional/fundrawtransaction-hd.py b/test/functional/fundrawtransaction-hd.py index e9500c6d6cd7..ade26fe8527a 100755 --- a/test/functional/fundrawtransaction-hd.py +++ b/test/functional/fundrawtransaction-hd.py @@ -439,9 +439,9 @@ def run_test(self): # locked wallet test self.nodes[1].encryptwallet("test") self.nodes.pop(1) - stop_node(self.nodes[0], 0) - stop_node(self.nodes[1], 2) - stop_node(self.nodes[2], 3) + self.stop_node(self.nodes[0], 0) + self.stop_node(self.nodes[1], 2) + self.stop_node(self.nodes[2], 3) self.nodes = start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, stderr=sys.stdout) # This test is not meant to test fee estimation and we'd like diff --git a/test/functional/llmq-chainlocks.py b/test/functional/llmq-chainlocks.py index 4963c0754260..d6feed6bcbce 100755 --- a/test/functional/llmq-chainlocks.py +++ b/test/functional/llmq-chainlocks.py @@ -71,7 +71,7 @@ def run_test(self): # Keep node connected and let it try to reorg the chain good_tip = self.nodes[0].getbestblockhash() # Restart it so that it forgets all the chainlocks from the past - stop_node(self.nodes[0], 0) + self.stop_node(self.nodes[0], 0) self.nodes[0] = start_node(0, self.options.tmpdir, self.extra_args) connect_nodes(self.nodes[0], 1) self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) diff --git a/test/functional/sporks.py b/test/functional/sporks.py index 65783a4e8804..56f8e8ced5cd 100755 --- a/test/functional/sporks.py +++ b/test/functional/sporks.py @@ -57,8 +57,8 @@ def run_test(self): assert(sent) # restart nodes to check spork persistence - stop_node(self.nodes[0], 0) - stop_node(self.nodes[1], 1) + self.stop_node(self.nodes[0], 0) + self.stop_node(self.nodes[1], 1) self.nodes[0] = start_node(0, self.options.tmpdir) self.nodes[1] = start_node(1, self.options.tmpdir) assert(not self.get_test_spork_state(self.nodes[0])) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 16cf71c345d0..24367735722a 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -458,7 +458,7 @@ def remove_mastermode(self, idx): def prepare_datadirs(self): # stop faucet node so that we can copy the datadir - stop_node(self.nodes[0], 0) + self.stop_node(self.nodes[0], 0) start_idx = len(self.nodes) for idx in range(0, self.mn_count): diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index e5016e25de64..40cad94733f6 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -68,7 +68,7 @@ def run_test (self): assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) self.log.info("Restore backup ...") - stop_node(self.nodes[1],1) + self.stop_node(self.nodes[1],1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") self.nodes[1] = self.start_node(1, self.options.tmpdir, self.extra_args[1], stderr=sys.stdout) From b791821c80df00d2d10aac2db2657ae35aa91147 Mon Sep 17 00:00:00 2001 From: Pasta Date: Thu, 4 Jul 2019 23:46:15 -0500 Subject: [PATCH 337/987] start_node -> self.start_node Signed-off-by: Pasta --- test/functional/dip3-deterministicmns.py | 4 ++-- test/functional/fundrawtransaction-hd.py | 2 +- test/functional/keypool-hd.py | 4 ++-- test/functional/llmq-chainlocks.py | 2 +- test/functional/p2p-fullblocktest.py | 2 +- test/functional/sporks.py | 4 ++-- test/functional/test_framework/test_framework.py | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/functional/dip3-deterministicmns.py b/test/functional/dip3-deterministicmns.py index c5d98267cbe3..4f980a8f67db 100755 --- a/test/functional/dip3-deterministicmns.py +++ b/test/functional/dip3-deterministicmns.py @@ -38,7 +38,7 @@ def start_controller_node(self, extra_args=None): args = self.extra_args if extra_args is not None: args += extra_args - self.nodes[0] = start_node(0, self.options.tmpdir, extra_args=args) + self.nodes[0] = self.start_node(0, self.options.tmpdir, extra_args=args) for i in range(1, self.num_nodes): if i < len(self.nodes) and self.nodes[i] is not None: connect_nodes_bi(self.nodes, 0, i) @@ -252,7 +252,7 @@ def start_mn(self, mn): while len(self.nodes) <= mn.idx: self.nodes.append(None) extra_args = ['-masternode=1', '-masternodeblsprivkey=%s' % mn.blsMnkey] - n = start_node(mn.idx, self.options.tmpdir, self.extra_args + extra_args, stderr=sys.stdout) + n = self.start_node(mn.idx, self.options.tmpdir, self.extra_args + extra_args, stderr=sys.stdout) self.nodes[mn.idx] = n for i in range(0, self.num_nodes): if i < len(self.nodes) and self.nodes[i] is not None and i != mn.idx: diff --git a/test/functional/fundrawtransaction-hd.py b/test/functional/fundrawtransaction-hd.py index ade26fe8527a..4880d1c8a7c6 100755 --- a/test/functional/fundrawtransaction-hd.py +++ b/test/functional/fundrawtransaction-hd.py @@ -443,7 +443,7 @@ def run_test(self): self.stop_node(self.nodes[1], 2) self.stop_node(self.nodes[2], 3) - self.nodes = start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, stderr=sys.stdout) + self.nodes = self.start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, stderr=sys.stdout) # This test is not meant to test fee estimation and we'd like # to be sure all txs are sent at a consistent desired feerate for node in self.nodes: diff --git a/test/functional/keypool-hd.py b/test/functional/keypool-hd.py index 51604cd4ea34..7a292d76fc59 100755 --- a/test/functional/keypool-hd.py +++ b/test/functional/keypool-hd.py @@ -28,7 +28,7 @@ def run_test(self): nodes[0].encryptwallet('test') bitcoind_processes[0].wait() # Restart node 0 - nodes[0] = start_node(0, self.options.tmpdir, ['-usehd=1'], stderr=sys.stdout) + nodes[0] = self.start_node(0, self.options.tmpdir, ['-usehd=1'], stderr=sys.stdout) # Keep creating keys addr = nodes[0].getnewaddress() addr_data = nodes[0].validateaddress(addr) @@ -104,7 +104,7 @@ def run_test(self): assert_equal(wi['keypoolsize'], 100) def setup_network(self): - self.nodes = start_nodes(1, self.options.tmpdir, [['-usehd=1']], stderr=sys.stdout) + self.nodes = self.start_nodes(1, self.options.tmpdir, [['-usehd=1']], stderr=sys.stdout) if __name__ == '__main__': KeyPoolTest().main() diff --git a/test/functional/llmq-chainlocks.py b/test/functional/llmq-chainlocks.py index d6feed6bcbce..ab85a9d7478b 100755 --- a/test/functional/llmq-chainlocks.py +++ b/test/functional/llmq-chainlocks.py @@ -72,7 +72,7 @@ def run_test(self): good_tip = self.nodes[0].getbestblockhash() # Restart it so that it forgets all the chainlocks from the past self.stop_node(self.nodes[0], 0) - self.nodes[0] = start_node(0, self.options.tmpdir, self.extra_args) + self.nodes[0] = self.start_node(0, self.options.tmpdir, self.extra_args) connect_nodes(self.nodes[0], 1) self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) # Now try to reorg the chain diff --git a/test/functional/p2p-fullblocktest.py b/test/functional/p2p-fullblocktest.py index f0602168601f..97fac35a92be 100755 --- a/test/functional/p2p-fullblocktest.py +++ b/test/functional/p2p-fullblocktest.py @@ -63,7 +63,7 @@ def __init__(self): def setup_network(self): # Must set '-dip3params=2000:2000' to create pre-dip3 blocks only - self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-whitelist=127.0.0.1', '-dip3params=2000:2000']], binary=[self.options.testbinary]) diff --git a/test/functional/sporks.py b/test/functional/sporks.py index 56f8e8ced5cd..e6918f20090b 100755 --- a/test/functional/sporks.py +++ b/test/functional/sporks.py @@ -59,8 +59,8 @@ def run_test(self): # restart nodes to check spork persistence self.stop_node(self.nodes[0], 0) self.stop_node(self.nodes[1], 1) - self.nodes[0] = start_node(0, self.options.tmpdir) - self.nodes[1] = start_node(1, self.options.tmpdir) + self.nodes[0] = self.start_node(0, self.options.tmpdir) + self.nodes[1] = self.start_node(1, self.options.tmpdir) assert(not self.get_test_spork_state(self.nodes[0])) assert(not self.get_test_spork_state(self.nodes[1])) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 24367735722a..56b447105539 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -465,7 +465,7 @@ def prepare_datadirs(self): copy_datadir(0, idx + start_idx, self.options.tmpdir) # restart faucet node - self.nodes[0] = start_node(0, self.options.tmpdir, self.extra_args) + self.nodes[0] = self.start_node(0, self.options.tmpdir, self.extra_args) def start_masternodes(self): start_idx = len(self.nodes) @@ -477,7 +477,7 @@ def start_masternodes(self): def do_start(idx): args = ['-masternode=1', '-masternodeblsprivkey=%s' % self.mninfo[idx].keyOperator] + self.extra_args - node = start_node(idx + start_idx, self.options.tmpdir, args) + node = self.start_node(idx + start_idx, self.options.tmpdir, args) self.mninfo[idx].nodeIdx = idx + start_idx self.mninfo[idx].node = node self.nodes[idx + start_idx] = node From de33753f0611f92c93cd292583b60c329f93e5fa Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 5 Jul 2019 12:11:56 -0500 Subject: [PATCH 338/987] Revert "Merge #10376: [tests] fix disconnect_ban intermittency" This reverts commit b6b486c274356e775f7f4a61c4d4c68435364546. --- test/functional/disconnect_ban.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/functional/disconnect_ban.py b/test/functional/disconnect_ban.py index bf513c841cab..b52870e26c97 100755 --- a/test/functional/disconnect_ban.py +++ b/test/functional/disconnect_ban.py @@ -3,7 +3,6 @@ # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test node disconnect and ban behavior""" -import time from test_framework.mininode import wait_until from test_framework.test_framework import BitcoinTestFramework @@ -58,18 +57,13 @@ def run_test(self): self.log.info("setban: test persistence across node restart") self.nodes[1].setban("127.0.0.0/32", "add") self.nodes[1].setban("127.0.0.0/24", "add") - # Set the mocktime so we can control when bans expire - old_time = int(time.time()) - self.nodes[1].setmocktime(old_time) self.nodes[1].setban("192.168.0.1", "add", 1) # ban for 1 seconds self.nodes[1].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) # ban for 1000 seconds listBeforeShutdown = self.nodes[1].listbanned() assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) set_mocktime(get_mocktime() + 2) set_node_times(self.nodes, get_mocktime()) - # Move time forward by 3 seconds so the third ban has expired - self.nodes[1].setmocktime(old_time + 3) - assert_equal(len(self.nodes[1].listbanned()), 3) + assert wait_until(lambda: len(self.nodes[1].listbanned()) == 3, timeout=10) self.stop_node(1) From 493f4336a3c4d5ff6d182c67343df9a1d7aece57 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 4 Jul 2019 18:15:52 +0300 Subject: [PATCH 339/987] fix tx rate --- test/functional/blockchain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index c0ebad6912fe..8dc500e6caea 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -47,9 +47,9 @@ def _test_getchaintxstats(self): chaintxstats = self.nodes[0].getchaintxstats(1) # 200 txs plus genesis tx assert_equal(chaintxstats['txcount'], 201) - # tx rate should be 1 per 10 minutes, or 1/600 + # tx rate should be 1 per ~2.6 minutes (156 seconds), or 1/156 # we have to round because of binary math - assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1)) + assert_equal(round(chaintxstats['txrate'] * 156, 10), Decimal(1)) def _test_gettxoutsetinfo(self): node = self.nodes[0] From 6c0b5053bcc58b5518bd699c8fb2938fbce14b6b Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 4 Jul 2019 17:48:01 +0300 Subject: [PATCH 340/987] Fix start_/stop_node-s --- test/functional/addressindex.py | 8 ++++---- test/functional/dip3-deterministicmns.py | 2 +- test/functional/fundrawtransaction-hd.py | 6 +++--- test/functional/llmq-chainlocks.py | 2 +- test/functional/multikeysporks.py | 10 +++++----- test/functional/p2p-fingerprint.py | 3 +-- test/functional/spentindex.py | 8 ++++---- test/functional/sporks.py | 4 ++-- test/functional/test_framework/test_framework.py | 6 +++--- test/functional/timestampindex.py | 8 ++++---- test/functional/txindex.py | 8 ++++---- test/functional/wallet-hd.py | 2 +- 12 files changed, 33 insertions(+), 34 deletions(-) diff --git a/test/functional/addressindex.py b/test/functional/addressindex.py index fdf4c39349ef..9cabdfa31f78 100755 --- a/test/functional/addressindex.py +++ b/test/functional/addressindex.py @@ -23,11 +23,11 @@ def __init__(self): def setup_network(self): self.nodes = [] # Nodes 0/1 are "wallet" nodes - self.nodes.append(start_node(0, self.options.tmpdir, ["-relaypriority=0"])) - self.nodes.append(start_node(1, self.options.tmpdir, ["-addressindex"])) + self.nodes.append(self.start_node(0, self.options.tmpdir, ["-relaypriority=0"])) + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-addressindex"])) # Nodes 2/3 are used for testing - self.nodes.append(start_node(2, self.options.tmpdir, ["-addressindex", "-relaypriority=0"])) - self.nodes.append(start_node(3, self.options.tmpdir, ["-addressindex"])) + self.nodes.append(self.start_node(2, self.options.tmpdir, ["-addressindex", "-relaypriority=0"])) + self.nodes.append(self.start_node(3, self.options.tmpdir, ["-addressindex"])) connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 3) diff --git a/test/functional/dip3-deterministicmns.py b/test/functional/dip3-deterministicmns.py index 4f980a8f67db..99403686d793 100755 --- a/test/functional/dip3-deterministicmns.py +++ b/test/functional/dip3-deterministicmns.py @@ -45,7 +45,7 @@ def start_controller_node(self, extra_args=None): def stop_controller_node(self): self.log.info("stopping controller node") - self.stop_node(self.nodes[0], 0) + self.stop_node(0) def restart_controller_node(self): self.stop_controller_node() diff --git a/test/functional/fundrawtransaction-hd.py b/test/functional/fundrawtransaction-hd.py index 4880d1c8a7c6..2e50c0cd5496 100755 --- a/test/functional/fundrawtransaction-hd.py +++ b/test/functional/fundrawtransaction-hd.py @@ -437,11 +437,11 @@ def run_test(self): ############################################################ # locked wallet test + self.stop_node(0) + self.stop_node(2) + self.stop_node(3) self.nodes[1].encryptwallet("test") self.nodes.pop(1) - self.stop_node(self.nodes[0], 0) - self.stop_node(self.nodes[1], 2) - self.stop_node(self.nodes[2], 3) self.nodes = self.start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, stderr=sys.stdout) # This test is not meant to test fee estimation and we'd like diff --git a/test/functional/llmq-chainlocks.py b/test/functional/llmq-chainlocks.py index ab85a9d7478b..cca1f9074162 100755 --- a/test/functional/llmq-chainlocks.py +++ b/test/functional/llmq-chainlocks.py @@ -71,7 +71,7 @@ def run_test(self): # Keep node connected and let it try to reorg the chain good_tip = self.nodes[0].getbestblockhash() # Restart it so that it forgets all the chainlocks from the past - self.stop_node(self.nodes[0], 0) + self.stop_node(0) self.nodes[0] = self.start_node(0, self.options.tmpdir, self.extra_args) connect_nodes(self.nodes[0], 1) self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) diff --git a/test/functional/multikeysporks.py b/test/functional/multikeysporks.py index e6bb77eb19b5..df1764b0603f 100755 --- a/test/functional/multikeysporks.py +++ b/test/functional/multikeysporks.py @@ -50,7 +50,7 @@ def setup_network(self): # keyid(hex): 1d1098b2b1f759b678a0a7a098637a9b898adcac # address(base58): yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui - self.nodes.append(start_node(0, self.options.tmpdir, + self.nodes.append(self.start_node(0, self.options.tmpdir, ["-sporkkey=931wyuRNVYvhg18Uu9bky5Qg1z4QbxaJ7fefNBzjBPiLRqcd33F", "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7", "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h", @@ -58,7 +58,7 @@ def setup_network(self): "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn", "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui", "-minsporkkeys=3"])) - self.nodes.append(start_node(1, self.options.tmpdir, + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-sporkkey=91vbXGMSWKGHom62986XtL1q2mQDA12ngcuUNNe5NfMSj44j7g3", "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7", "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h", @@ -66,7 +66,7 @@ def setup_network(self): "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn", "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui", "-minsporkkeys=3"])) - self.nodes.append(start_node(2, self.options.tmpdir, + self.nodes.append(self.start_node(2, self.options.tmpdir, ["-sporkkey=92bxUjPT5AhgXuXJwfGGXqhomY2SdQ55MYjXyx9DZNxCABCSsRH", "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7", "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h", @@ -74,7 +74,7 @@ def setup_network(self): "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn", "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui", "-minsporkkeys=3"])) - self.nodes.append(start_node(3, self.options.tmpdir, + self.nodes.append(self.start_node(3, self.options.tmpdir, ["-sporkkey=934yPXiVGf4RCY2qTs2Bt5k3TEtAiAg12sMxCt8yVWbSU7p3fuD", "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7", "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h", @@ -82,7 +82,7 @@ def setup_network(self): "-sporkaddr=ycbRQWbovrhQMTuxg9p4LAuW5SCMAKqPrn", "-sporkaddr=yc5TGfcHYoLCrcbVy4umsiDjsYUn39vLui", "-minsporkkeys=3"])) - self.nodes.append(start_node(4, self.options.tmpdir, + self.nodes.append(self.start_node(4, self.options.tmpdir, ["-sporkkey=92Cxwia363Wg2qGF1fE5z4GKi8u7r1nrWQXdtsj2ACZqaDPSihD", "-sporkaddr=ygcG5S2pQz2U1UAaHvU6EznKZW7yapKMA7", "-sporkaddr=yfLSXFfipnkgYioD6L8aUNyfRgEBuJv48h", diff --git a/test/functional/p2p-fingerprint.py b/test/functional/p2p-fingerprint.py index aae51ea5d352..1e4a86bb7fb9 100755 --- a/test/functional/p2p-fingerprint.py +++ b/test/functional/p2p-fingerprint.py @@ -26,8 +26,7 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, - p2p_port, - start_nodes) + p2p_port) class P2PFingerprintTest(BitcoinTestFramework): def __init__(self): diff --git a/test/functional/spentindex.py b/test/functional/spentindex.py index 5147f275b168..57be6f6ba496 100755 --- a/test/functional/spentindex.py +++ b/test/functional/spentindex.py @@ -23,11 +23,11 @@ def __init__(self): def setup_network(self): self.nodes = [] # Nodes 0/1 are "wallet" nodes - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir, ["-spentindex"])) + self.nodes.append(self.start_node(0, self.options.tmpdir)) + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-spentindex"])) # Nodes 2/3 are used for testing - self.nodes.append(start_node(2, self.options.tmpdir, ["-spentindex"])) - self.nodes.append(start_node(3, self.options.tmpdir, ["-spentindex", "-txindex"])) + self.nodes.append(self.start_node(2, self.options.tmpdir, ["-spentindex"])) + self.nodes.append(self.start_node(3, self.options.tmpdir, ["-spentindex", "-txindex"])) connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 3) diff --git a/test/functional/sporks.py b/test/functional/sporks.py index e6918f20090b..b72045bfc18d 100755 --- a/test/functional/sporks.py +++ b/test/functional/sporks.py @@ -57,8 +57,8 @@ def run_test(self): assert(sent) # restart nodes to check spork persistence - self.stop_node(self.nodes[0], 0) - self.stop_node(self.nodes[1], 1) + self.stop_node(0) + self.stop_node(1) self.nodes[0] = self.start_node(0, self.options.tmpdir) self.nodes[1] = self.start_node(1, self.options.tmpdir) assert(not self.get_test_spork_state(self.nodes[0])) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 56b447105539..7d6f94cad481 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -407,7 +407,7 @@ def __init__(self, num_nodes, masterodes_count, extra_args, fast_dip3_enforcemen def create_simple_node(self): idx = len(self.nodes) args = self.extra_args - self.nodes.append(start_node(idx, self.options.tmpdir, args)) + self.nodes.append(self.start_node(idx, self.options.tmpdir, args)) for i in range(0, idx): connect_nodes(self.nodes[i], idx) @@ -458,7 +458,7 @@ def remove_mastermode(self, idx): def prepare_datadirs(self): # stop faucet node so that we can copy the datadir - self.stop_node(self.nodes[0], 0) + self.stop_node(0) start_idx = len(self.nodes) for idx in range(0, self.mn_count): @@ -514,7 +514,7 @@ def do_connect(idx): def setup_network(self): self.nodes = [] # create faucet node for collateral and transactions - self.nodes.append(start_node(0, self.options.tmpdir, self.extra_args)) + self.nodes.append(self.start_node(0, self.options.tmpdir, self.extra_args)) required_balance = MASTERNODE_COLLATERAL * self.mn_count + 1 while self.nodes[0].getbalance() < required_balance: set_mocktime(get_mocktime() + 1) diff --git a/test/functional/timestampindex.py b/test/functional/timestampindex.py index 5f615008d89f..74db7573b2d1 100755 --- a/test/functional/timestampindex.py +++ b/test/functional/timestampindex.py @@ -21,11 +21,11 @@ def __init__(self): def setup_network(self): self.nodes = [] # Nodes 0/1 are "wallet" nodes - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir, ["-timestampindex"])) + self.nodes.append(self.start_node(0, self.options.tmpdir)) + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-timestampindex"])) # Nodes 2/3 are used for testing - self.nodes.append(start_node(2, self.options.tmpdir)) - self.nodes.append(start_node(3, self.options.tmpdir, ["-timestampindex"])) + self.nodes.append(self.start_node(2, self.options.tmpdir)) + self.nodes.append(self.start_node(3, self.options.tmpdir, ["-timestampindex"])) connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 3) diff --git a/test/functional/txindex.py b/test/functional/txindex.py index 889d2eefc342..f3dc4f211c3a 100755 --- a/test/functional/txindex.py +++ b/test/functional/txindex.py @@ -23,11 +23,11 @@ def __init__(self): def setup_network(self): self.nodes = [] # Nodes 0/1 are "wallet" nodes - self.nodes.append(start_node(0, self.options.tmpdir)) - self.nodes.append(start_node(1, self.options.tmpdir, ["-txindex"])) + self.nodes.append(self.start_node(0, self.options.tmpdir)) + self.nodes.append(self.start_node(1, self.options.tmpdir, ["-txindex"])) # Nodes 2/3 are used for testing - self.nodes.append(start_node(2, self.options.tmpdir, ["-txindex"])) - self.nodes.append(start_node(3, self.options.tmpdir, ["-txindex"])) + self.nodes.append(self.start_node(2, self.options.tmpdir, ["-txindex"])) + self.nodes.append(self.start_node(3, self.options.tmpdir, ["-txindex"])) connect_nodes(self.nodes[0], 1) connect_nodes(self.nodes[0], 2) connect_nodes(self.nodes[0], 3) diff --git a/test/functional/wallet-hd.py b/test/functional/wallet-hd.py index 40cad94733f6..292040162a72 100755 --- a/test/functional/wallet-hd.py +++ b/test/functional/wallet-hd.py @@ -68,7 +68,7 @@ def run_test (self): assert_equal(self.nodes[1].getbalance(), num_hd_adds + 1) self.log.info("Restore backup ...") - self.stop_node(self.nodes[1],1) + self.stop_node(1) os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat") shutil.copyfile(tmpdir + "/hd.bak", tmpdir + "/node1/regtest/wallet.dat") self.nodes[1] = self.start_node(1, self.options.tmpdir, self.extra_args[1], stderr=sys.stdout) From 3fe858e53f5fbf0123ae1d3d221164342fc5c194 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 5 Jul 2019 22:21:00 -0500 Subject: [PATCH 341/987] wait for node1 in fundrawtransaction(-hd).py tests --- test/functional/fundrawtransaction-hd.py | 1 + test/functional/fundrawtransaction.py | 1 + 2 files changed, 2 insertions(+) diff --git a/test/functional/fundrawtransaction-hd.py b/test/functional/fundrawtransaction-hd.py index 2e50c0cd5496..d17a18182d3e 100755 --- a/test/functional/fundrawtransaction-hd.py +++ b/test/functional/fundrawtransaction-hd.py @@ -442,6 +442,7 @@ def run_test(self): self.stop_node(3) self.nodes[1].encryptwallet("test") self.nodes.pop(1) + wait_node(1) self.nodes = self.start_nodes(4, self.options.tmpdir, [['-usehd=1']] * self.num_nodes, stderr=sys.stdout) # This test is not meant to test fee estimation and we'd like diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index b8a57aae4c19..b9488f9b431a 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -454,6 +454,7 @@ def run_test(self): self.stop_node(3) self.nodes[1].encryptwallet("test") self.nodes.pop(1) + wait_node(1) self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, [['-usehd=0']] * self.num_nodes) # This test is not meant to test fee estimation and we'd like From bdec34c949bf564d1ff0e53d4b44da5a5ebfa204 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Sat, 6 Jul 2019 17:07:03 -0500 Subject: [PATCH 342/987] remove DS mixes once they have been included in a chainlocked block (#3015) * remove DS mixes once they have been included in a chainlocked block Signed-off-by: Pasta * Use multiple if checks instead of one line conditional Signed-off-by: Pasta --- src/privatesend/privatesend.cpp | 15 +++++++++------ src/privatesend/privatesend.h | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/privatesend/privatesend.cpp b/src/privatesend/privatesend.cpp index 30c694eaab36..c02f19385e8e 100644 --- a/src/privatesend/privatesend.cpp +++ b/src/privatesend/privatesend.cpp @@ -17,6 +17,7 @@ #include "validation.h" #include "llmq/quorums_instantsend.h" +#include "llmq/quorums_chainlocks.h" #include @@ -115,10 +116,12 @@ bool CPrivateSendBroadcastTx::CheckSignature(const CBLSPublicKey& blsPubKey) con return true; } -bool CPrivateSendBroadcastTx::IsExpired(int nHeight) +bool CPrivateSendBroadcastTx::IsExpired(const CBlockIndex* pindex) { - // expire confirmed DSTXes after ~1h since confirmation - return (nConfirmedHeight != -1) && (nHeight - nConfirmedHeight > 24); + // expire confirmed DSTXes after ~1h since confirmation or chainlocked confirmation + if (nConfirmedHeight == -1 || pindex->nHeight < nConfirmedHeight) return false; // not mined yet + if (pindex->nHeight - nConfirmedHeight > 24) return true; // mined more then an hour ago + return llmq::chainLocksHandler->HasChainLock(pindex->nHeight, *pindex->phashBlock); } bool CPrivateSendBroadcastTx::IsValidStructure() @@ -487,12 +490,12 @@ CPrivateSendBroadcastTx CPrivateSend::GetDSTX(const uint256& hash) return (it == mapDSTX.end()) ? CPrivateSendBroadcastTx() : it->second; } -void CPrivateSend::CheckDSTXes(int nHeight) +void CPrivateSend::CheckDSTXes(const CBlockIndex* pindex) { LOCK(cs_mapdstx); auto it = mapDSTX.begin(); while (it != mapDSTX.end()) { - if (it->second.IsExpired(nHeight)) { + if (it->second.IsExpired(pindex)) { mapDSTX.erase(it++); } else { ++it; @@ -504,7 +507,7 @@ void CPrivateSend::CheckDSTXes(int nHeight) void CPrivateSend::UpdatedBlockTip(const CBlockIndex* pindex) { if (pindex && masternodeSync.IsBlockchainSynced()) { - CheckDSTXes(pindex->nHeight); + CheckDSTXes(pindex); } } diff --git a/src/privatesend/privatesend.h b/src/privatesend/privatesend.h index 5a2872bcd0c8..95e22e74e368 100644 --- a/src/privatesend/privatesend.h +++ b/src/privatesend/privatesend.h @@ -351,7 +351,7 @@ class CPrivateSendBroadcastTx bool CheckSignature(const CBLSPublicKey& blsPubKey) const; void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; } - bool IsExpired(int nHeight); + bool IsExpired(const CBlockIndex* pindex); bool IsValidStructure(); }; @@ -427,7 +427,7 @@ class CPrivateSend static CCriticalSection cs_mapdstx; - static void CheckDSTXes(int nHeight); + static void CheckDSTXes(const CBlockIndex* pindex); public: static void InitStandardDenominations(); From 72a1b6f59d56edf31d0ae57741c020e1db4ec74d Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 8 Jul 2019 10:50:28 +0200 Subject: [PATCH 343/987] Use sync_with_ping to ensure that we don't start generating blocks too early --- test/functional/sendheaders.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/functional/sendheaders.py b/test/functional/sendheaders.py index 0d0fcfe96d0c..22770b61c24f 100755 --- a/test/functional/sendheaders.py +++ b/test/functional/sendheaders.py @@ -239,6 +239,8 @@ def run_test(self): # Test logic begins here inv_node.wait_for_verack() test_node.wait_for_verack() + inv_node.sync_with_ping() + test_node.sync_with_ping() self.test_null_locators(test_node) self.test_nonnull_locators(test_node, inv_node) From 85fcf32c973fb42369264b2b774d2d5b9114264f Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Mon, 8 Jul 2019 17:17:30 +0200 Subject: [PATCH 344/987] Remove support for InstantSend locked gobject collaterals (#3019) --- src/governance/governance-object.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/governance/governance-object.cpp b/src/governance/governance-object.cpp index 0cac4f4b9a9a..3501dbeccee3 100644 --- a/src/governance/governance-object.cpp +++ b/src/governance/governance-object.cpp @@ -8,7 +8,6 @@ #include "governance-validators.h" #include "governance-vote.h" #include "governance.h" -#include "instantsend.h" #include "masternode/masternode-meta.h" #include "masternode/masternode-sync.h" #include "messagesigner.h" @@ -16,8 +15,6 @@ #include "util.h" #include "validation.h" -#include "llmq/quorums_instantsend.h" - #include #include @@ -589,8 +586,7 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC } } - if ((nConfirmationsIn < GOVERNANCE_FEE_CONFIRMATIONS) && - (!instantsend.IsLockedInstantSendTransaction(nCollateralHash) || llmq::quorumInstantSendManager->IsLocked(nCollateralHash))) { + if ((nConfirmationsIn < GOVERNANCE_FEE_CONFIRMATIONS)) { strError = strprintf("Collateral requires at least %d confirmations to be relayed throughout the network (it has only %d)", GOVERNANCE_FEE_CONFIRMATIONS, nConfirmationsIn); if (nConfirmationsIn >= GOVERNANCE_MIN_RELAY_FEE_CONFIRMATIONS) { fMissingConfirmations = true; From 37659cd5221d0a357b63428177649d89173a4b1b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Mon, 22 May 2017 08:14:17 +0200 Subject: [PATCH 345/987] Merge #10431: Prevent shadowing the global dustRelayFee MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 43c5877 Prevent shadowing the global dustRelayFee. (Pavel Janík) Tree-SHA512: 9765931a7753c484990003396afd0bb65a53f42d1cad9502017720618ce90b3c5ae68591db01e3524adecdbe6925a5eeeebf04012ba644ef3b65073af207ae5d --- src/policy/policy.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 9832697475f6..1b1b30017f97 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -15,7 +15,7 @@ #include -CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee) +CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) { // "Dust" is defined in terms of CTransaction::minRelayTxFee, which has units duffs-per-kilobyte. // If you'd pay more than 1/3 in fees to spend something, then we consider it dust. @@ -28,12 +28,12 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee) return 0; size_t nSize = GetSerializeSize(txout, SER_DISK, 0)+148u; - return 3 * dustRelayFee.GetFee(nSize); + return 3 * dustRelayFeeIn.GetFee(nSize); } -bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee) +bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn) { - return (txout.nValue < GetDustThreshold(txout, dustRelayFee)); + return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn)); } /** From 42985c31bb8f939ba621ab7e70b802cd3aff2fa9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 6 Jun 2017 10:08:14 +0200 Subject: [PATCH 346/987] Merge #10463: Names: BIP9 vs versionbits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit b463bc9 scripted-diff: s/BIP9DeploymentInfo/VBDeploymentInfo/ (Jorge Timón) 29c0719 Rename -bip9params to -vbparams (shaolinfry) Tree-SHA512: a8a2bf6e24a4a7fc82f784c78c0cd92472e9ba55ce3fb22dafef3eccdcfccb2da5a6078fbeec1a8a4b6ab1f1b226976c5aba964dd5e3d029a21b109a7c044374 --- src/chainparams.cpp | 6 +++--- src/chainparams.h | 6 +++--- src/init.cpp | 16 ++++++++-------- src/rpc/mining.cpp | 6 +++--- src/validation.cpp | 2 +- src/versionbits.cpp | 2 +- src/versionbits.h | 4 ++-- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 99de1bd92229..da0002bfc8d4 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -83,7 +83,7 @@ static CBlock CreateGenesisBlock(uint32_t nTime, uint32_t nNonce, uint32_t nBits } -void CChainParams::UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold) +void CChainParams::UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold) { consensus.vDeployments[d].nStartTime = nStartTime; consensus.vDeployments[d].nTimeout = nTimeout; @@ -877,9 +877,9 @@ void SelectParams(const std::string& network) globalChainParams = CreateChainParams(network); } -void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold) +void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold) { - globalChainParams->UpdateBIP9Parameters(d, nStartTime, nTimeout, nWindowSize, nThreshold); + globalChainParams->UpdateVersionBitsParameters(d, nStartTime, nTimeout, nWindowSize, nThreshold); } void UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight) diff --git a/src/chainparams.h b/src/chainparams.h index 2a0a2b597190..e47b9ce5b535 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -84,7 +84,7 @@ class CChainParams const std::vector& FixedSeeds() const { return vFixedSeeds; } const CCheckpointData& Checkpoints() const { return checkpointData; } const ChainTxData& TxData() const { return chainTxData; } - void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold); + void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold); void UpdateDIP3Parameters(int nActivationHeight, int nEnforcementHeight); void UpdateBudgetParameters(int nMasternodePaymentsStartBlock, int nBudgetPaymentsStartBlock, int nSuperblockStartBlock); int PoolMinParticipants() const { return nPoolMinParticipants; } @@ -143,9 +143,9 @@ const CChainParams &Params(); void SelectParams(const std::string& chain); /** - * Allows modifying the BIP9 regtest parameters. + * Allows modifying the Version Bits regtest parameters. */ -void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold); +void UpdateVersionBitsParameters(Consensus::DeploymentPos d, int64_t nStartTime, int64_t nTimeout, int64_t nWindowSize, int64_t nThreshold); /** * Allows modifying the DIP3 activation and enforcement height diff --git a/src/init.cpp b/src/init.cpp index 705807601e2e..22f833fc97f4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -566,7 +566,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-limitancestorsize=", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT)); strUsage += HelpMessageOpt("-limitdescendantcount=", strprintf("Do not accept transactions if any ancestor would have or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT)); strUsage += HelpMessageOpt("-limitdescendantsize=", strprintf("Do not accept transactions if any ancestor would have more than kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT)); - strUsage += HelpMessageOpt("-bip9params=::(::)", "Use given start/end times for specified BIP9 deployment (regtest-only). Specifying window and threshold is optional."); + strUsage += HelpMessageOpt("-vbparams=::(::)", "Use given start/end times for specified version bits deployment (regtest-only). Specifying window and threshold is optional."); strUsage += HelpMessageOpt("-watchquorums=", strprintf("Watch and validate quorum communication (default: %u)", llmq::DEFAULT_WATCH_QUORUMS)); } strUsage += HelpMessageOpt("-debug=", strprintf(_("Output debugging information (default: %u, supplying is optional)"), 0) + ". " + @@ -1326,16 +1326,16 @@ bool AppInitParameterInteraction() nMaxTipAge = gArgs.GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE); - if (gArgs.IsArgSet("-bip9params")) { - // Allow overriding BIP9 parameters for testing + if (gArgs.IsArgSet("-vbparams")) { + // Allow overriding version bits parameters for testing if (!chainparams.MineBlocksOnDemand()) { - return InitError("BIP9 parameters may only be overridden on regtest."); + return InitError("Version bits parameters may only be overridden on regtest."); } - for (const std::string& strDeployment : gArgs.GetArgs("-bip9params")) { + for (const std::string& strDeployment : gArgs.GetArgs("-vbparams")) { std::vector vDeploymentParams; boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":")); if (vDeploymentParams.size() != 3 && vDeploymentParams.size() != 5) { - return InitError("BIP9 parameters malformed, expecting deployment:start:end or deployment:start:end:window:threshold"); + return InitError("Version bits parameters malformed, expecting deployment:start:end or deployment:start:end:window:threshold"); } int64_t nStartTime, nTimeout, nWindowSize = -1, nThreshold = -1; if (!ParseInt64(vDeploymentParams[1], &nStartTime)) { @@ -1356,9 +1356,9 @@ bool AppInitParameterInteraction() for (int j=0; j<(int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++j) { if (vDeploymentParams[0].compare(VersionBitsDeploymentInfo[j].name) == 0) { - UpdateBIP9Parameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, nWindowSize, nThreshold); + UpdateVersionBitsParameters(Consensus::DeploymentPos(j), nStartTime, nTimeout, nWindowSize, nThreshold); found = true; - LogPrintf("Setting BIP9 activation parameters for %s to start=%ld, timeout=%ld, window=%ld, threshold=%ld\n", vDeploymentParams[0], nStartTime, nTimeout, nWindowSize, nThreshold); + LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, window=%ld, threshold=%ld\n", vDeploymentParams[0], nStartTime, nTimeout, nWindowSize, nThreshold); break; } } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 79836a70656a..85efec369c1b 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -313,7 +313,7 @@ static UniValue BIP22ValidationResult(const CValidationState& state) } std::string gbt_vb_name(const Consensus::DeploymentPos pos) { - const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; + const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; std::string s = vbinfo.name; if (!vbinfo.gbt_force) { s.insert(s.begin(), '!'); @@ -648,7 +648,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) // FALL THROUGH to get vbavailable set... case THRESHOLD_STARTED: { - const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; + const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit)); if (setClientRules.find(vbinfo.name) == setClientRules.end()) { if (!vbinfo.gbt_force) { @@ -661,7 +661,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) case THRESHOLD_ACTIVE: { // Add to rules only - const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; + const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; aRules.push_back(gbt_vb_name(pos)); if (setClientRules.find(vbinfo.name) == setClientRules.end()) { // Not supported by the client; make sure it's safe to proceed diff --git a/src/validation.cpp b/src/validation.cpp index 56c8319abdd7..9756d96f6cb5 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1860,7 +1860,7 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; i++) { Consensus::DeploymentPos pos = Consensus::DeploymentPos(i); ThresholdState state = VersionBitsState(pindexPrev, params, pos, versionbitscache); - const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; + const struct VBDeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos]; if (vbinfo.check_mn_protocol && state == THRESHOLD_STARTED && fCheckMasternodesUpgraded) { // TODO implement new logic for MN upgrade checks (e.g. with LLMQ based feature/version voting) } diff --git a/src/versionbits.cpp b/src/versionbits.cpp index f7bf5f81dccc..e1d6ae47d708 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -5,7 +5,7 @@ #include "versionbits.h" #include "consensus/params.h" -const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = { +const struct VBDeploymentInfo VersionBitsDeploymentInfo[Consensus::MAX_VERSION_BITS_DEPLOYMENTS] = { { /*.name =*/ "testdummy", /*.gbt_force =*/ true, diff --git a/src/versionbits.h b/src/versionbits.h index 7e5f5b1e4539..79bbcb85576c 100644 --- a/src/versionbits.h +++ b/src/versionbits.h @@ -30,7 +30,7 @@ enum ThresholdState { // will either be NULL or a block with (height + 1) % Period() == 0. typedef std::map ThresholdConditionCache; -struct BIP9DeploymentInfo { +struct VBDeploymentInfo { /** Deployment name */ const char *name; /** Whether GBT clients can safely ignore this rule in simplified usage */ @@ -47,7 +47,7 @@ struct BIP9Stats { bool possible; }; -extern const struct BIP9DeploymentInfo VersionBitsDeploymentInfo[]; +extern const struct VBDeploymentInfo VersionBitsDeploymentInfo[]; /** * Abstract class that implements BIP9-style threshold logic, and caches results. From 648848b797ae2bf2c21c3c6060fe27811b71acc9 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 6 Jun 2017 23:54:23 +0200 Subject: [PATCH 347/987] Merge #10331: Share config between util and functional tests 8ad5bde Merge bctest.py into bitcoin-util-test.py (John Newbery) 95836c5 Use shared config file for functional and util tests (John Newbery) 89fcd35 Use an .ini config file for environment vars in bitcoin-util-test.py (John Newbery) e9265df Change help_text in bitcoin-util-test.py to a docstring. (John Newbery) ce58e93 Change bitcoin-util-test.py to use Python3 (John Newbery) Tree-SHA512: 66dab0b4a8546aee0dfaef134a165f1447aff4c0ec335754bbc7d9e55909721c62f09cdbf4b22d02ac1fcd5a9b66780f91e1cc4d8687fae7288cc9072a23a78f --- .gitignore | 4 +- Makefile.am | 4 - configure.ac | 8 +- src/Makefile.test.include | 2 +- test/{functional => }/config.ini.in | 2 +- test/functional/test_runner.py | 2 +- test/util/bctest.py | 139 ----------------------- test/util/bitcoin-util-test.py | 167 +++++++++++++++++++++++++--- test/util/buildenv.py.in | 4 - 9 files changed, 157 insertions(+), 175 deletions(-) rename test/{functional => }/config.ini.in (90%) delete mode 100644 test/util/bctest.py delete mode 100644 test/util/buildenv.py.in diff --git a/.gitignore b/.gitignore index a1c24fd7222f..d4b84032d66d 100644 --- a/.gitignore +++ b/.gitignore @@ -88,7 +88,6 @@ Dash-Qt.app # Unit-tests Makefile.test dash-qt_test -src/test/buildenv.py # Resources cpp qrc_*.cpp @@ -109,8 +108,7 @@ coverage_percent.txt linux-coverage-build linux-build win32-build -test/functional/config.ini -test/util/buildenv.py +test/config.ini test/cache/* !src/leveldb*/Makefile diff --git a/Makefile.am b/Makefile.am index 12a48f61fcd6..9de5e5c37d95 100644 --- a/Makefile.am +++ b/Makefile.am @@ -223,7 +223,6 @@ dist_noinst_SCRIPTS = autogen.sh EXTRA_DIST = $(top_srcdir)/share/genbuild.sh test/functional/test_runner.py test/functional $(DIST_CONTRIB) $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING) $(BIN_CHECKS) EXTRA_DIST += \ - test/util/bctest.py \ test/util/bitcoin-util-test.py \ test/util/data/bitcoin-util-test.json \ test/util/data/blanktxv1.hex \ @@ -265,9 +264,6 @@ EXTRA_DIST += \ CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER) -# This file is problematic for out-of-tree builds if it exists. -DISTCLEANFILES = test/util/buildenv.pyc - .INTERMEDIATE: $(COVERAGE_INFO) DISTCHECK_CONFIGURE_FLAGS = --enable-man diff --git a/configure.ac b/configure.ac index 7c83915e7eb4..b24105efd037 100644 --- a/configure.ac +++ b/configure.ac @@ -1218,13 +1218,11 @@ AC_SUBST(ZMQ_LIBS) AC_SUBST(PROTOBUF_LIBS) AC_SUBST(QR_LIBS) AC_SUBST(DSYMUTIL_FLAT) -AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/functional/config.ini]) -AC_CONFIG_FILES([test/util/buildenv.py],[chmod +x test/util/buildenv.py]) +AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile share/setup.nsi share/qt/Info.plist test/config.ini]) AC_CONFIG_FILES([contrib/devtools/split-debug.sh],[chmod +x contrib/devtools/split-debug.sh]) AC_CONFIG_FILES([doc/Doxyfile]) AC_CONFIG_LINKS([test/functional/test_runner.py:test/functional/test_runner.py]) AC_CONFIG_LINKS([test/util/bitcoin-util-test.py:test/util/bitcoin-util-test.py]) -AC_CONFIG_LINKS([test/util/bctest.py:test/util/bctest.py]) dnl boost's m4 checks do something really nasty: they export these vars. As a dnl result, they leak into secp256k1's configure and crazy things happen. @@ -1272,8 +1270,8 @@ esac dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows case ${OS} in *Windows*) - sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' test/functional/config.ini > test/functional/config-2.ini - mv test/functional/config-2.ini test/functional/config.ini + sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' test/config.ini > test/config-2.ini + mv test/config-2.ini test/config.ini ;; esac diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 61fdf60e4f6d..9ad118ce9499 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -142,7 +142,7 @@ dash_test_clean : FORCE check-local: @echo "Running test/util/bitcoin-util-test.py..." - $(PYTHON) $(top_builddir)/test/util/bitcoin-util-test.py + $(top_builddir)/test/util/bitcoin-util-test.py $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check if EMBEDDED_UNIVALUE $(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C univalue check diff --git a/test/functional/config.ini.in b/test/config.ini.in similarity index 90% rename from test/functional/config.ini.in rename to test/config.ini.in index 29586c555d53..35ee092be4fc 100644 --- a/test/functional/config.ini.in +++ b/test/config.ini.in @@ -3,7 +3,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. # These environment variables are set by the build process and read by -# test/functional/test_runner.py +# test/functional/test_runner.py and test/util/bitcoin-util-test.py [environment] SRCDIR=@abs_top_srcdir@ diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 854fa1f68432..041890cd03c6 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -194,7 +194,7 @@ def main(): # Read config generated by configure. config = configparser.ConfigParser() - configfile = os.path.abspath(os.path.dirname(__file__)) + "/config.ini" + configfile = os.path.abspath(os.path.dirname(__file__)) + "/../config.ini" config.read_file(open(configfile)) passon_args.append("--configfile=%s" % configfile) diff --git a/test/util/bctest.py b/test/util/bctest.py deleted file mode 100644 index b17cf77ae312..000000000000 --- a/test/util/bctest.py +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright 2014 BitPay Inc. -# Copyright 2016 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -from __future__ import division,print_function,unicode_literals -import subprocess -import os -import json -import sys -import binascii -import difflib -import logging -import pprint - -def parse_output(a, fmt): - """Parse the output according to specified format. - - Raise an error if the output can't be parsed.""" - if fmt == 'json': # json: compare parsed data - return json.loads(a) - elif fmt == 'hex': # hex: parse and compare binary data - return binascii.a2b_hex(a.strip()) - else: - raise NotImplementedError("Don't know how to compare %s" % fmt) - -def bctest(testDir, testObj, buildenv): - """Runs a single test, comparing output and RC to expected output and RC. - - Raises an error if input can't be read, executable fails, or output/RC - are not as expected. Error is caught by bctester() and reported. - """ - # Get the exec names and arguments - execprog = buildenv.BUILDDIR + "/src/" + testObj['exec'] + buildenv.exeext - execargs = testObj['args'] - execrun = [execprog] + execargs - - # Read the input data (if there is any) - stdinCfg = None - inputData = None - if "input" in testObj: - filename = testDir + "/" + testObj['input'] - inputData = open(filename).read() - stdinCfg = subprocess.PIPE - - # Read the expected output data (if there is any) - outputFn = None - outputData = None - if "output_cmp" in testObj: - outputFn = testObj['output_cmp'] - outputType = os.path.splitext(outputFn)[1][1:] # output type from file extension (determines how to compare) - try: - outputData = open(testDir + "/" + outputFn).read() - except: - logging.error("Output file " + outputFn + " can not be opened") - raise - if not outputData: - logging.error("Output data missing for " + outputFn) - raise Exception - - # Run the test - proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE,universal_newlines=True) - try: - outs = proc.communicate(input=inputData) - except OSError: - logging.error("OSError, Failed to execute " + execprog) - raise - - if outputData: - data_mismatch, formatting_mismatch = False, False - # Parse command output and expected output - try: - a_parsed = parse_output(outs[0], outputType) - except Exception as e: - logging.error('Error parsing command output as %s: %s' % (outputType,e)) - raise - try: - b_parsed = parse_output(outputData, outputType) - except Exception as e: - logging.error('Error parsing expected output %s as %s: %s' % (outputFn,outputType,e)) - raise - # Compare data - if a_parsed != b_parsed: - logging.error("Output data mismatch for " + outputFn + " (format " + outputType + ")") - data_mismatch = True - # Compare formatting - if outs[0] != outputData: - error_message = "Output formatting mismatch for " + outputFn + ":\n" - error_message += "".join(difflib.context_diff(outputData.splitlines(True), - outs[0].splitlines(True), - fromfile=outputFn, - tofile="returned")) - logging.error(error_message) - formatting_mismatch = True - - assert not data_mismatch and not formatting_mismatch - - # Compare the return code to the expected return code - wantRC = 0 - if "return_code" in testObj: - wantRC = testObj['return_code'] - if proc.returncode != wantRC: - logging.error("Return code mismatch for " + outputFn) - raise Exception - - if "error_txt" in testObj: - want_error = testObj["error_txt"] - # Compare error text - # TODO: ideally, we'd compare the strings exactly and also assert - # That stderr is empty if no errors are expected. However, bitcoin-tx - # emits DISPLAY errors when running as a windows application on - # linux through wine. Just assert that the expected error text appears - # somewhere in stderr. - if want_error not in outs[1]: - logging.error("Error mismatch:\n" + "Expected: " + want_error + "\nReceived: " + outs[1].rstrip()) - raise Exception - -def bctester(testDir, input_basename, buildenv): - """ Loads and parses the input file, runs all tests and reports results""" - input_filename = testDir + "/" + input_basename - raw_data = open(input_filename).read() - input_data = json.loads(raw_data) - - failed_testcases = [] - - for testObj in input_data: - try: - bctest(testDir, testObj, buildenv) - logging.info("PASSED: " + testObj["description"]) - except: - logging.info("FAILED: " + testObj["description"]) - failed_testcases.append(testObj["description"]) - - if failed_testcases: - error_message = "FAILED_TESTCASES:\n" - error_message += pprint.pformat(failed_testcases, width=400) - logging.error(error_message) - sys.exit(1) - else: - sys.exit(0) diff --git a/test/util/bitcoin-util-test.py b/test/util/bitcoin-util-test.py index e09a25159d2c..d15d6a6011cc 100755 --- a/test/util/bitcoin-util-test.py +++ b/test/util/bitcoin-util-test.py @@ -1,26 +1,30 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright 2014 BitPay Inc. -# Copyright 2016 The Bitcoin Core developers +# Copyright 2016-2017 The Bitcoin Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -from __future__ import division,print_function,unicode_literals -import os -import sys -import argparse -import logging +"""Test framework for bitcoin utils. -help_text="""Test framework for bitcoin utils. - -Runs automatically during `make check`. +Runs automatically during `make check`. Can also be run manually.""" -if __name__ == '__main__': - sys.path.append(os.path.dirname(os.path.abspath(__file__))) - import buildenv - import bctest +import argparse +import binascii +import configparser +import difflib +import json +import logging +import os +import pprint +import subprocess +import sys - parser = argparse.ArgumentParser(description=help_text) +def main(): + config = configparser.ConfigParser() + config.read_file(open(os.path.dirname(__file__) + "/../config.ini")) + + parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('-v', '--verbose', action='store_true') args = parser.parse_args() verbose = args.verbose @@ -31,6 +35,135 @@ level = logging.ERROR formatter = '%(asctime)s - %(levelname)s - %(message)s' # Add the format/level to the logger - logging.basicConfig(format = formatter, level=level) + logging.basicConfig(format=formatter, level=level) + + bctester(config["environment"]["SRCDIR"] + "/test/util/data", "bitcoin-util-test.json", config["environment"]) + +def bctester(testDir, input_basename, buildenv): + """ Loads and parses the input file, runs all tests and reports results""" + input_filename = testDir + "/" + input_basename + raw_data = open(input_filename).read() + input_data = json.loads(raw_data) + + failed_testcases = [] + + for testObj in input_data: + try: + bctest(testDir, testObj, buildenv) + logging.info("PASSED: " + testObj["description"]) + except: + logging.info("FAILED: " + testObj["description"]) + failed_testcases.append(testObj["description"]) - bctest.bctester(buildenv.SRCDIR + "/test/util/data", "bitcoin-util-test.json", buildenv) + if failed_testcases: + error_message = "FAILED_TESTCASES:\n" + error_message += pprint.pformat(failed_testcases, width=400) + logging.error(error_message) + sys.exit(1) + else: + sys.exit(0) + +def bctest(testDir, testObj, buildenv): + """Runs a single test, comparing output and RC to expected output and RC. + + Raises an error if input can't be read, executable fails, or output/RC + are not as expected. Error is caught by bctester() and reported. + """ + # Get the exec names and arguments + execprog = buildenv["BUILDDIR"] + "/src/" + testObj['exec'] + buildenv["EXEEXT"] + execargs = testObj['args'] + execrun = [execprog] + execargs + + # Read the input data (if there is any) + stdinCfg = None + inputData = None + if "input" in testObj: + filename = testDir + "/" + testObj['input'] + inputData = open(filename).read() + stdinCfg = subprocess.PIPE + + # Read the expected output data (if there is any) + outputFn = None + outputData = None + if "output_cmp" in testObj: + outputFn = testObj['output_cmp'] + outputType = os.path.splitext(outputFn)[1][1:] # output type from file extension (determines how to compare) + try: + outputData = open(testDir + "/" + outputFn).read() + except: + logging.error("Output file " + outputFn + " can not be opened") + raise + if not outputData: + logging.error("Output data missing for " + outputFn) + raise Exception + + # Run the test + proc = subprocess.Popen(execrun, stdin=stdinCfg, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) + try: + outs = proc.communicate(input=inputData) + except OSError: + logging.error("OSError, Failed to execute " + execprog) + raise + + if outputData: + data_mismatch, formatting_mismatch = False, False + # Parse command output and expected output + try: + a_parsed = parse_output(outs[0], outputType) + except Exception as e: + logging.error('Error parsing command output as %s: %s' % (outputType, e)) + raise + try: + b_parsed = parse_output(outputData, outputType) + except Exception as e: + logging.error('Error parsing expected output %s as %s: %s' % (outputFn, outputType, e)) + raise + # Compare data + if a_parsed != b_parsed: + logging.error("Output data mismatch for " + outputFn + " (format " + outputType + ")") + data_mismatch = True + # Compare formatting + if outs[0] != outputData: + error_message = "Output formatting mismatch for " + outputFn + ":\n" + error_message += "".join(difflib.context_diff(outputData.splitlines(True), + outs[0].splitlines(True), + fromfile=outputFn, + tofile="returned")) + logging.error(error_message) + formatting_mismatch = True + + assert not data_mismatch and not formatting_mismatch + + # Compare the return code to the expected return code + wantRC = 0 + if "return_code" in testObj: + wantRC = testObj['return_code'] + if proc.returncode != wantRC: + logging.error("Return code mismatch for " + outputFn) + raise Exception + + if "error_txt" in testObj: + want_error = testObj["error_txt"] + # Compare error text + # TODO: ideally, we'd compare the strings exactly and also assert + # That stderr is empty if no errors are expected. However, bitcoin-tx + # emits DISPLAY errors when running as a windows application on + # linux through wine. Just assert that the expected error text appears + # somewhere in stderr. + if want_error not in outs[1]: + logging.error("Error mismatch:\n" + "Expected: " + want_error + "\nReceived: " + outs[1].rstrip()) + raise Exception + +def parse_output(a, fmt): + """Parse the output according to specified format. + + Raise an error if the output can't be parsed.""" + if fmt == 'json': # json: compare parsed data + return json.loads(a) + elif fmt == 'hex': # hex: parse and compare binary data + return binascii.a2b_hex(a.strip()) + else: + raise NotImplementedError("Don't know how to compare %s" % fmt) + +if __name__ == '__main__': + main() diff --git a/test/util/buildenv.py.in b/test/util/buildenv.py.in deleted file mode 100644 index 33030b0348ab..000000000000 --- a/test/util/buildenv.py.in +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env python -exeext="@EXEEXT@" -SRCDIR="@abs_top_srcdir@" -BUILDDIR="@abs_top_builddir@" From 5edec30db00ae10dbf4744bb89e3e5ffd43271fa Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 6 Jun 2017 16:40:48 -0700 Subject: [PATCH 348/987] Merge #10523: Perform member initialization in initialization lists where possible 656dbd871 Perform member initialization in initialization lists where possible (practicalswift) Tree-SHA512: 048380f4da23ab1eaaf471801a01dbd76f2235afb686c1489b30a6bac109195134afc83414b8378d3482a9042d537ec62d30136dadb9347cf06b07fb5c693208 --- src/primitives/block.h | 5 +---- src/protocol.cpp | 6 +----- src/rpc/server.h | 2 +- src/wallet/wallet.h | 5 +---- 4 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/primitives/block.h b/src/primitives/block.h index dda9a9d609b7..4ec1cf75ca5d 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -130,10 +130,7 @@ struct CBlockLocator CBlockLocator() {} - CBlockLocator(const std::vector& vHaveIn) - { - vHave = vHaveIn; - } + CBlockLocator(const std::vector& vHaveIn) : vHave(vHaveIn) {} ADD_SERIALIZE_METHODS; diff --git a/src/protocol.cpp b/src/protocol.cpp index 48146ee8f9d4..3449b54f80ca 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -257,11 +257,7 @@ CInv::CInv() hash.SetNull(); } -CInv::CInv(int typeIn, const uint256& hashIn) -{ - type = typeIn; - hash = hashIn; -} +CInv::CInv(int typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {} CInv::CInv(const std::string& strType, const uint256& hashIn) { diff --git a/src/rpc/server.h b/src/rpc/server.h index 98e2bddbe5db..de3b74ead22d 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -48,7 +48,7 @@ class JSONRPCRequest std::string URI; std::string authUser; - JSONRPCRequest() { id = NullUniValue; params = NullUniValue; fHelp = false; } + JSONRPCRequest() : id(NullUniValue), params(NullUniValue), fHelp(false) {} void parse(const UniValue& valRequest); }; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0dc655672a80..7eb94c2cdca4 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -159,10 +159,7 @@ class CAddressBookData std::string name; std::string purpose; - CAddressBookData() - { - purpose = "unknown"; - } + CAddressBookData() : purpose("unknown") {} typedef std::map StringMap; StringMap destdata; From 57c5cfb0f67c1944373ddb113c1630caa181849f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Jun 2017 14:59:41 -0700 Subject: [PATCH 349/987] Merge #10321: Use FastRandomContext for all tests e94584858 scripted-diff: Use new naming style for insecure_rand* functions (Pieter Wuille) 2fcd9cc86 scripted-diff: Use randbits/bool instead of randrange where possible (Pieter Wuille) 2ada67852 Use randbits instead of ad-hoc emulation in prevector tests (Pieter Wuille) 5f0b04eed Replace rand() & ((1 << N) - 1) with randbits(N) (Pieter Wuille) 3ecabae36 Replace more rand() % NUM by randranges (Pieter Wuille) efee1db21 scripted-diff: use insecure_rand256/randrange more (Pieter Wuille) 1119927df Add various insecure_rand wrappers for tests (Pieter Wuille) 124d13a58 Merge test_random.h into test_bitcoin.h (Pieter Wuille) 90620d66c scripted-diff: Rename cuckoo tests' local rand context (Pieter Wuille) 37e864eb9 Add FastRandomContext::rand256() and ::randbytes() (Pieter Wuille) Tree-SHA512: d09705a3ec718ae792f7d66a75401903ba7b9c9d3fc36669d6e3b9242f0194738106be26baefc8a8e3fa6df7c9a35978c71c0c430278a028b331df23a3ea3070 --- src/Makefile.test.include | 1 - src/random.cpp | 20 ++++++++ src/random.h | 6 +++ src/test/DoS_tests.cpp | 4 +- src/test/blockencodings_tests.cpp | 10 ++-- src/test/bloom_tests.cpp | 2 +- src/test/checkqueue_tests.cpp | 10 ++-- src/test/coins_tests.cpp | 79 +++++++++++++++---------------- src/test/crypto_tests.cpp | 3 +- src/test/cuckoocache_tests.cpp | 24 +++++----- src/test/dbwrapper_tests.cpp | 20 ++++---- src/test/hash_tests.cpp | 2 +- src/test/merkle_tests.cpp | 5 +- src/test/miner_tests.cpp | 4 +- src/test/pmt_tests.cpp | 9 ++-- src/test/pow_tests.cpp | 6 +-- src/test/prevector_tests.cpp | 67 +++++++++++++------------- src/test/random_tests.cpp | 7 +++ src/test/sighash_tests.cpp | 27 +++++------ src/test/skiplist_tests.cpp | 11 ++--- src/test/test_dash.cpp | 2 +- src/test/test_dash.h | 21 ++++++++ src/test/test_random.h | 29 ------------ src/test/util_tests.cpp | 5 +- src/test/versionbits_tests.cpp | 13 +++-- src/wallet/test/crypto_tests.cpp | 5 +- 26 files changed, 202 insertions(+), 190 deletions(-) delete mode 100644 src/test/test_random.h diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 9ad118ce9499..c0b422858690 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -87,7 +87,6 @@ BITCOIN_TESTS =\ test/test_dash.cpp \ test/test_dash.h \ test/test_dash_main.cpp \ - test/test_random.h \ test/testutil.cpp \ test/testutil.h \ test/timedata_tests.cpp \ diff --git a/src/random.cpp b/src/random.cpp index 4f28ebf4948c..0668966756f0 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -315,6 +315,26 @@ void FastRandomContext::RandomSeed() requires_seed = false; } +uint256 FastRandomContext::rand256() +{ + if (bytebuf_size < 32) { + FillByteBuffer(); + } + uint256 ret; + memcpy(ret.begin(), bytebuf + 64 - bytebuf_size, 32); + bytebuf_size -= 32; + return ret; +} + +std::vector FastRandomContext::randbytes(size_t len) +{ + std::vector ret(len); + if (len > 0) { + rng.Output(&ret[0], len); + } + return ret; +} + FastRandomContext::FastRandomContext(const uint256& seed) : requires_seed(false), bytebuf_size(0), bitbuf_size(0) { rng.SetKey(seed.begin(), 32); diff --git a/src/random.h b/src/random.h index 29b7b2c8abce..306c9355830b 100644 --- a/src/random.h +++ b/src/random.h @@ -120,9 +120,15 @@ class FastRandomContext { return rand32(nMax); } + /** Generate random bytes. */ + std::vector randbytes(size_t len); + /** Generate a random 32-bit integer. */ uint32_t rand32() { return randbits(32); } + /** generate a random uint256. */ + uint256 rand256(); + /** Generate a random boolean. */ bool randbool() { return randbits(1); } }; diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 531b896a2fc5..7db06e2f1ee5 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -129,7 +129,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime) CTransactionRef RandomOrphan() { std::map::iterator it; - it = mapOrphanTransactions.lower_bound(GetRandHash()); + it = mapOrphanTransactions.lower_bound(InsecureRand256()); if (it == mapOrphanTransactions.end()) it = mapOrphanTransactions.begin(); return it->second.tx; @@ -148,7 +148,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans) CMutableTransaction tx; tx.vin.resize(1); tx.vin[0].prevout.n = 0; - tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].prevout.hash = InsecureRand256(); tx.vin[0].scriptSig << OP_1; tx.vout.resize(1); tx.vout[0].nValue = 1*CENT; diff --git a/src/test/blockencodings_tests.cpp b/src/test/blockencodings_tests.cpp index b74bef3f6a82..a1cdad48da5c 100644 --- a/src/test/blockencodings_tests.cpp +++ b/src/test/blockencodings_tests.cpp @@ -30,16 +30,16 @@ static CBlock BuildBlockTestCase() { block.vtx.resize(3); block.vtx[0] = MakeTransactionRef(tx); block.nVersion = 42; - block.hashPrevBlock = GetRandHash(); + block.hashPrevBlock = InsecureRand256(); block.nBits = 0x207fffff; - tx.vin[0].prevout.hash = GetRandHash(); + tx.vin[0].prevout.hash = InsecureRand256(); tx.vin[0].prevout.n = 0; block.vtx[1] = MakeTransactionRef(tx); tx.vin.resize(10); for (size_t i = 0; i < tx.vin.size(); i++) { - tx.vin[i].prevout.hash = GetRandHash(); + tx.vin[i].prevout.hash = InsecureRand256(); tx.vin[i].prevout.n = 0; } block.vtx[2] = MakeTransactionRef(tx); @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) block.vtx.resize(1); block.vtx[0] = MakeTransactionRef(std::move(coinbase)); block.nVersion = 42; - block.hashPrevBlock = GetRandHash(); + block.hashPrevBlock = InsecureRand256(); block.nBits = 0x207fffff; bool mutated; @@ -316,7 +316,7 @@ BOOST_AUTO_TEST_CASE(EmptyBlockRoundTripTest) BOOST_AUTO_TEST_CASE(TransactionsRequestSerializationTest) { BlockTransactionsRequest req1; - req1.blockhash = GetRandHash(); + req1.blockhash = InsecureRand256(); req1.indexes.resize(4); req1.indexes[0] = 0; req1.indexes[1] = 1; diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 16b3d067cd05..21ea5c25b06b 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -563,7 +563,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_4_test_update_none) static std::vector RandomData() { - uint256 r = GetRandHash(); + uint256 r = InsecureRand256(); return std::vector(r.begin(), r.end()); } diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index 72e4d3b37888..dee199cd9a80 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -160,7 +160,7 @@ void Correct_Queue_range(std::vector range) FakeCheckCheckCompletion::n_calls = 0; CCheckQueueControl control(small_queue.get()); while (total) { - vChecks.resize(std::min(total, (size_t) GetRand(10))); + vChecks.resize(std::min(total, (size_t) InsecureRandRange(10))); total -= vChecks.size(); control.Add(vChecks); } @@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Correct_Random) { std::vector range; range.reserve(100000/1000); - for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)GetRand(std::min((size_t)1000, ((size_t)100000) - i)))) + for (size_t i = 2; i < 100000; i += std::max((size_t)1, (size_t)InsecureRandRange(std::min((size_t)1000, ((size_t)100000) - i)))) range.push_back(i); Correct_Queue_range(range); } @@ -224,7 +224,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Catches_Failure) CCheckQueueControl control(fail_queue.get()); size_t remaining = i; while (remaining) { - size_t r = GetRand(10); + size_t r = InsecureRandRange(10); std::vector vChecks; vChecks.reserve(r); @@ -286,7 +286,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_UniqueCheck) { CCheckQueueControl control(queue.get()); while (total) { - size_t r = GetRand(10); + size_t r = InsecureRandRange(10); std::vector vChecks; for (size_t k = 0; k < r && total; k++) vChecks.emplace_back(--total); @@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(test_CheckQueue_Memory) { CCheckQueueControl control(queue.get()); while (total) { - size_t r = GetRand(10); + size_t r = InsecureRandRange(10); std::vector vChecks; for (size_t k = 0; k < r && total; k++) { total--; diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 42ab30431a2a..22cb2ca44b18 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -8,7 +8,6 @@ #include "undo.h" #include "utilstrencodings.h" #include "test/test_dash.h" -#include "test/test_random.h" #include "validation.h" #include "consensus/validation.h" @@ -44,7 +43,7 @@ class CCoinsViewTest : public CCoinsView return false; } coin = it->second; - if (coin.IsSpent() && insecure_rand() % 2 == 0) { + if (coin.IsSpent() && InsecureRandBool() == 0) { // Randomly return false in case of an empty entry. return false; } @@ -59,7 +58,7 @@ class CCoinsViewTest : public CCoinsView if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Same optimization used in CCoinsViewDB is to only write dirty entries. map_[it->first] = it->second.coin; - if (it->second.coin.IsSpent() && insecure_rand() % 3 == 0) { + if (it->second.coin.IsSpent() && InsecureRandRange(3) == 0) { // Randomly delete empty entries on write. map_.erase(it->first); } @@ -134,13 +133,13 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) std::vector txids; txids.resize(NUM_SIMULATION_ITERATIONS / 8); for (unsigned int i = 0; i < txids.size(); i++) { - txids[i] = GetRandHash(); + txids[i] = InsecureRand256(); } for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { // Do a random modification. { - uint256 txid = txids[insecure_rand() % txids.size()]; // txid we're going to modify in this iteration. + uint256 txid = txids[InsecureRandRange(txids.size())]; // txid we're going to modify in this iteration. Coin& coin = result[COutPoint(txid, 0)]; // Determine whether to test HaveCoin before or after Access* (or both). As these functions @@ -150,7 +149,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) bool test_havecoin_after = (insecure_rand() & 0x3) == 0; // TODO change to InsecureRandBits(2) when backporting Bitcoin #10321 bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false; - const Coin& entry = (insecure_rand() % 500 == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0)); + const Coin& entry = (InsecureRandRange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0)); BOOST_CHECK(coin == entry); BOOST_CHECK(!test_havecoin_before || result_havecoin == !entry.IsSpent()); @@ -159,20 +158,20 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) BOOST_CHECK(ret == !entry.IsSpent()); } - if (insecure_rand() % 5 == 0 || coin.IsSpent()) { + if (InsecureRandRange(5) == 0 || coin.IsSpent()) { Coin newcoin; - newcoin.out.nValue = insecure_rand(); + newcoin.out.nValue = InsecureRand32(); newcoin.nHeight = 1; - if (insecure_rand() % 16 == 0 && coin.IsSpent()) { - newcoin.out.scriptPubKey.assign(1 + (insecure_rand() & 0x3F), OP_RETURN); + if (InsecureRandRange(16) == 0 && coin.IsSpent()) { + newcoin.out.scriptPubKey.assign(1 + InsecureRandBits(6), OP_RETURN); BOOST_CHECK(newcoin.out.scriptPubKey.IsUnspendable()); added_an_unspendable_entry = true; } else { - newcoin.out.scriptPubKey.assign(insecure_rand() & 0x3F, 0); // Random sizes so we can test memory usage accounting + newcoin.out.scriptPubKey.assign(InsecureRandBits(6), 0); // Random sizes so we can test memory usage accounting (coin.IsSpent() ? added_an_entry : updated_an_entry) = true; coin = newcoin; } - stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), !coin.IsSpent() || insecure_rand() & 1); + stack.back()->AddCoin(COutPoint(txid, 0), std::move(newcoin), !coin.IsSpent() || InsecureRand32() & 1); } else { removed_an_entry = true; coin.Clear(); @@ -181,15 +180,15 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } // One every 10 iterations, remove a random entry from the cache - if (insecure_rand() % 10 == 0) { - COutPoint out(txids[insecure_rand() % txids.size()], 0); - int cacheid = insecure_rand() % stack.size(); + if (InsecureRandRange(10) == 0) { + COutPoint out(txids[InsecureRand32() % txids.size()], 0); + int cacheid = InsecureRand32() % stack.size(); stack[cacheid]->Uncache(out); uncached_an_entry |= !stack[cacheid]->HaveCoinInCache(out); } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (auto it = result.begin(); it != result.end(); it++) { bool have = stack.back()->HaveCoin(it->first); const Coin& coin = stack.back()->AccessCoin(it->first); @@ -207,22 +206,22 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) } } - if (insecure_rand() % 100 == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_rand() % 2 == 0) { - unsigned int flushIndex = insecure_rand() % (stack.size() - 1); + if (stack.size() > 1 && InsecureRandBool() == 0) { + unsigned int flushIndex = InsecureRandRange(stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_rand() % 100 == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_rand() % 2 == 0) { + if (stack.size() > 0 && InsecureRandBool() == 0) { //Remove the top cache stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) { + if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { //Add a new cache CCoinsView* tip = &base; if (stack.size() > 0) { @@ -262,7 +261,7 @@ UtxoData utxoData; UtxoData::iterator FindRandomFrom(const std::set &utxoSet) { assert(utxoSet.size()); - auto utxoSetIt = utxoSet.lower_bound(COutPoint(GetRandHash(), 0)); + auto utxoSetIt = utxoSet.lower_bound(COutPoint(InsecureRand256(), 0)); if (utxoSetIt == utxoSet.end()) { utxoSetIt = utxoSet.begin(); } @@ -295,7 +294,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) std::set utxoset; for (unsigned int i = 0; i < NUM_SIMULATION_ITERATIONS; i++) { - uint32_t randiter = insecure_rand(); + uint32_t randiter = InsecureRand32(); // 19/20 txs add a new transaction if (randiter % 20 < 19) { @@ -303,14 +302,14 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) tx.vin.resize(1); tx.vout.resize(1); tx.vout[0].nValue = i; //Keep txs unique unless intended to duplicate - tx.vout[0].scriptPubKey.assign(insecure_rand() & 0x3F, 0); // Random sizes so we can test memory usage accounting - unsigned int height = insecure_rand(); + tx.vout[0].scriptPubKey.assign(InsecureRand32() & 0x3F, 0); // Random sizes so we can test memory usage accounting + unsigned int height = InsecureRand32(); Coin old_coin; // 2/20 times create a new coinbase if (randiter % 20 < 2 || coinbase_coins.size() < 10) { // 1/10 of those times create a duplicate coinbase - if (insecure_rand() % 10 == 0 && coinbase_coins.size()) { + if (InsecureRandRange(10) == 0 && coinbase_coins.size()) { auto utxod = FindRandomFrom(coinbase_coins); // Reuse the exact same coinbase tx = std::get<0>(utxod->second); @@ -420,7 +419,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // Once every 1000 iterations and at the end, verify the full cache. - if (insecure_rand() % 1000 == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { + if (InsecureRandRange(1000) == 1 || i == NUM_SIMULATION_ITERATIONS - 1) { for (auto it = result.begin(); it != result.end(); it++) { bool have = stack.back()->HaveCoin(it->first); const Coin& coin = stack.back()->AccessCoin(it->first); @@ -430,31 +429,31 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) } // One every 10 iterations, remove a random entry from the cache - if (utxoset.size() > 1 && insecure_rand() % 30 == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); + if (utxoset.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(utxoset)->first); } - if (disconnected_coins.size() > 1 && insecure_rand() % 30 == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); + if (disconnected_coins.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(disconnected_coins)->first); } - if (duplicate_coins.size() > 1 && insecure_rand() % 30 == 0) { - stack[insecure_rand() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); + if (duplicate_coins.size() > 1 && InsecureRandRange(30) == 0) { + stack[InsecureRand32() % stack.size()]->Uncache(FindRandomFrom(duplicate_coins)->first); } - if (insecure_rand() % 100 == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, flush an intermediate cache - if (stack.size() > 1 && insecure_rand() % 2 == 0) { - unsigned int flushIndex = insecure_rand() % (stack.size() - 1); + if (stack.size() > 1 && InsecureRandBool() == 0) { + unsigned int flushIndex = InsecureRandRange(stack.size() - 1); stack[flushIndex]->Flush(); } } - if (insecure_rand() % 100 == 0) { + if (InsecureRandRange(100) == 0) { // Every 100 iterations, change the cache stack. - if (stack.size() > 0 && insecure_rand() % 2 == 0) { + if (stack.size() > 0 && InsecureRandBool() == 0) { stack.back()->Flush(); delete stack.back(); stack.pop_back(); } - if (stack.size() == 0 || (stack.size() < 4 && insecure_rand() % 2)) { + if (stack.size() == 0 || (stack.size() < 4 && InsecureRandBool())) { CCoinsView* tip = &base; if (stack.size() > 0) { tip = stack.back(); diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index 5a76d781e90c..e3171107d645 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -13,7 +13,6 @@ #include "random.h" #include "utilstrencodings.h" #include "test/test_dash.h" -#include "test/test_random.h" #include @@ -39,7 +38,7 @@ void TestVector(const Hasher &h, const In &in, const Out &out) { Hasher hasher(h); size_t pos = 0; while (pos < in.size()) { - size_t len = insecure_rand() % ((in.size() - pos + 1) / 2 + 1); + size_t len = InsecureRandRange((in.size() - pos + 1) / 2 + 1); hasher.Write((unsigned char*)&in[pos], len); pos += len; if (pos > 0 && pos + 2 * out.size() > in.size() && pos < in.size()) { diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 8a1196870c4d..7c6abc4d707e 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -23,18 +23,18 @@ * using BOOST_CHECK_CLOSE to fail. * */ -FastRandomContext insecure_rand(true); +FastRandomContext local_rand_ctx(true); BOOST_AUTO_TEST_SUITE(cuckoocache_tests); -/** insecure_GetRandHash fills in a uint256 from insecure_rand +/** insecure_GetRandHash fills in a uint256 from local_rand_ctx */ void insecure_GetRandHash(uint256& t) { uint32_t* ptr = (uint32_t*)t.begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } @@ -45,7 +45,7 @@ void insecure_GetRandHash(uint256& t) */ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) { - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); CuckooCache::cache cc{}; size_t megabytes = 4; cc.setup_bytes(megabytes << 20); @@ -66,7 +66,7 @@ BOOST_AUTO_TEST_CASE(test_cuckoocache_no_fakes) template double test_cache(size_t megabytes, double load) { - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -76,7 +76,7 @@ double test_cache(size_t megabytes, double load) for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)hashes[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -137,7 +137,7 @@ template void test_cache_erase(size_t megabytes) { double load = 1; - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -147,7 +147,7 @@ void test_cache_erase(size_t megabytes) for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)hashes[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -200,7 +200,7 @@ template void test_cache_erase_parallel(size_t megabytes) { double load = 1; - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); std::vector hashes; Cache set{}; size_t bytes = megabytes * (1 << 20); @@ -210,7 +210,7 @@ void test_cache_erase_parallel(size_t megabytes) for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)hashes[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } /** We make a copy of the hashes because future optimizations of the * cuckoocache may overwrite the inserted element, so the test is @@ -302,7 +302,7 @@ void test_cache_generations() // iterations with non-deterministic values, so it isn't "overfit" to the // specific entropy in FastRandomContext(true) and implementation of the // cache. - insecure_rand = FastRandomContext(true); + local_rand_ctx = FastRandomContext(true); // block_activity models a chunk of network activity. n_insert elements are // adde to the cache. The first and last n/4 are stored for removal later @@ -319,7 +319,7 @@ void test_cache_generations() for (uint32_t i = 0; i < n_insert; ++i) { uint32_t* ptr = (uint32_t*)inserts[i].begin(); for (uint8_t j = 0; j < 8; ++j) - *(ptr++) = insecure_rand.rand32(); + *(ptr++) = local_rand_ctx.rand32(); } for (uint32_t i = 0; i < n_insert / 4; ++i) reads.push_back(inserts[i]); diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index ae470b48e964..571e06f312c3 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(dbwrapper) fs::path ph = fs::temp_directory_path() / fs::unique_path(); CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); uint256 res; // Ensure that we're doing real obfuscation when obfuscate=true @@ -53,11 +53,11 @@ BOOST_AUTO_TEST_CASE(dbwrapper_batch) CDBWrapper dbw(ph, (1 << 20), true, false, obfuscate); char key = 'i'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); char key2 = 'j'; - uint256 in2 = GetRandHash(); + uint256 in2 = InsecureRand256(); char key3 = 'k'; - uint256 in3 = GetRandHash(); + uint256 in3 = InsecureRand256(); uint256 res; CDBBatch batch(dbw); @@ -91,10 +91,10 @@ BOOST_AUTO_TEST_CASE(dbwrapper_iterator) // The two keys are intentionally chosen for ordering char key = 'j'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); BOOST_CHECK(dbw.Write(key, in)); char key2 = 'k'; - uint256 in2 = GetRandHash(); + uint256 in2 = InsecureRand256(); BOOST_CHECK(dbw.Write(key2, in2)); std::unique_ptr it(const_cast(&dbw)->NewIterator()); @@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) // Set up a non-obfuscated wrapper to write some initial data. CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); uint256 res; BOOST_CHECK(dbw->Write(key, in)); @@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE(existing_data_no_obfuscate) BOOST_CHECK(!odbw.IsEmpty()); // There should be existing data BOOST_CHECK(is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); // The key should be an empty string - uint256 in2 = GetRandHash(); + uint256 in2 = InsecureRand256(); uint256 res3; // Check that we can write successfully @@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) // Set up a non-obfuscated wrapper to write some initial data. CDBWrapper* dbw = new CDBWrapper(ph, (1 << 10), false, false, false); char key = 'k'; - uint256 in = GetRandHash(); + uint256 in = InsecureRand256(); uint256 res; BOOST_CHECK(dbw->Write(key, in)); @@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(existing_data_reindex) BOOST_CHECK(!odbw.Read(key, res2)); BOOST_CHECK(!is_null_key(dbwrapper_private::GetObfuscateKey(odbw))); - uint256 in2 = GetRandHash(); + uint256 in2 = InsecureRand256(); uint256 res3; // Check that we can write successfully diff --git a/src/test/hash_tests.cpp b/src/test/hash_tests.cpp index 604a1a2a2d80..26cd35a7e036 100644 --- a/src/test/hash_tests.cpp +++ b/src/test/hash_tests.cpp @@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE(siphash) for (int i = 0; i < 16; ++i) { uint64_t k1 = ctx.rand64(); uint64_t k2 = ctx.rand64(); - uint256 x = GetRandHash(); + uint256 x = InsecureRand256(); uint32_t n = ctx.rand32(); uint8_t nb[4]; WriteLE32(nb, n); diff --git a/src/test/merkle_tests.cpp b/src/test/merkle_tests.cpp index 6a19de5d82ad..56b897ffb727 100644 --- a/src/test/merkle_tests.cpp +++ b/src/test/merkle_tests.cpp @@ -4,7 +4,6 @@ #include "consensus/merkle.h" #include "test/test_dash.h" -#include "test/test_random.h" #include @@ -68,7 +67,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) { for (int i = 0; i < 32; i++) { // Try 32 block sizes: all sizes from 0 to 16 inclusive, and then 15 random sizes. - int ntx = (i <= 16) ? i : 17 + (insecure_rand() % 4000); + int ntx = (i <= 16) ? i : 17 + (InsecureRandRange(4000)); // Try up to 3 mutations. for (int mutate = 0; mutate <= 3; mutate++) { int duplicate1 = mutate >= 1 ? 1 << ctz(ntx) : 0; // The last how many transactions to duplicate first. @@ -121,7 +120,7 @@ BOOST_AUTO_TEST_CASE(merkle_test) // If ntx <= 16, try all branches. Otherwise, try 16 random ones. int mtx = loop; if (ntx > 16) { - mtx = insecure_rand() % ntx; + mtx = InsecureRandRange(ntx); } std::vector newBranch = BlockMerkleBranch(block, mtx); std::vector oldBranch = BlockGetMerkleBranch(block, merkleTree, mtx); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index d145da43f5bd..3f860cffdaec 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // while (chainActive.Tip()->nHeight < 209999) { // CBlockIndex* prev = chainActive.Tip(); // CBlockIndex* next = new CBlockIndex(); - // next->phashBlock = new uint256(GetRandHash()); + // next->phashBlock = new uint256(InsecureRand256()); // pcoinsTip->SetBestBlock(next->GetBlockHash()); // next->pprev = prev; // next->nHeight = prev->nHeight + 1; @@ -403,7 +403,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // while (chainActive.Tip()->nHeight < 210000) { // CBlockIndex* prev = chainActive.Tip(); // CBlockIndex* next = new CBlockIndex(); - // next->phashBlock = new uint256(GetRandHash()); + // next->phashBlock = new uint256(InsecureRand256()); // pcoinsTip->SetBestBlock(next->GetBlockHash()); // next->pprev = prev; // next->nHeight = prev->nHeight + 1; diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index 81d279f66f59..aa672d563f43 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -10,7 +10,6 @@ #include "arith_uint256.h" #include "version.h" #include "test/test_dash.h" -#include "test/test_random.h" #include @@ -22,8 +21,8 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree public: // flip one bit in one of the hashes - this should break the authentication void Damage() { - unsigned int n = insecure_rand() % vHash.size(); - int bit = insecure_rand() % 256; + unsigned int n = InsecureRandRange(vHash.size()); + int bit = InsecureRandBits(8); *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7); } }; @@ -32,7 +31,7 @@ BOOST_FIXTURE_TEST_SUITE(pmt_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(pmt_test1) { - seed_insecure_rand(false); + SeedInsecureRand(false); static const unsigned int nTxCounts[] = {1, 4, 7, 17, 56, 100, 127, 256, 312, 513, 1000, 4095}; for (int i = 0; i < 12; i++) { @@ -63,7 +62,7 @@ BOOST_AUTO_TEST_CASE(pmt_test1) std::vector vMatch(nTx, false); std::vector vMatchTxid1; for (unsigned int j=0; jGetConsensus()); BOOST_CHECK_EQUAL(tdiff, p1->GetBlockTime() - p2->GetBlockTime()); diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index a5886a0d8d96..2c36f12389ee 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -9,7 +9,6 @@ #include "streams.h" #include "test/test_dash.h" -#include "test/test_random.h" #include @@ -188,7 +187,7 @@ class prevector_tester { } prevector_tester() { - seed_insecure_rand(); + SeedInsecureRand(); rand_seed = insecure_rand_seed; rand_cache = insecure_rand_ctx; } @@ -199,67 +198,65 @@ BOOST_AUTO_TEST_CASE(PrevectorTestInt) for (int j = 0; j < 64; j++) { prevector_tester<8, int> test; for (int i = 0; i < 2048; i++) { - int r = insecure_rand(); - if ((r % 4) == 0) { - test.insert(insecure_rand() % (test.size() + 1), insecure_rand()); + if (InsecureRandBits(2) == 0) { + test.insert(InsecureRandRange(test.size() + 1), InsecureRand32()); } - if (test.size() > 0 && ((r >> 2) % 4) == 1) { - test.erase(insecure_rand() % test.size()); + if (test.size() > 0 && InsecureRandBits(2) == 1) { + test.erase(InsecureRandRange(test.size())); } - if (((r >> 4) % 8) == 2) { - int new_size = std::max(0, std::min(30, test.size() + (insecure_rand() % 5) - 2)); + if (InsecureRandBits(3) == 2) { + int new_size = std::max(0, std::min(30, test.size() + (InsecureRandRange(5)) - 2)); test.resize(new_size); } - if (((r >> 7) % 8) == 3) { - test.insert(insecure_rand() % (test.size() + 1), 1 + (insecure_rand() % 2), insecure_rand()); + if (InsecureRandBits(3) == 3) { + test.insert(InsecureRandRange(test.size() + 1), 1 + InsecureRandBool(), InsecureRand32()); } - if (((r >> 10) % 8) == 4) { - int del = std::min(test.size(), 1 + (insecure_rand() % 2)); - int beg = insecure_rand() % (test.size() + 1 - del); + if (InsecureRandBits(3) == 4) { + int del = std::min(test.size(), 1 + (InsecureRandBool())); + int beg = InsecureRandRange(test.size() + 1 - del); test.erase(beg, beg + del); } - if (((r >> 13) % 16) == 5) { - test.push_back(insecure_rand()); + if (InsecureRandBits(4) == 5) { + test.push_back(InsecureRand32()); } - if (test.size() > 0 && ((r >> 17) % 16) == 6) { + if (test.size() > 0 && InsecureRandBits(4) == 6) { test.pop_back(); } - if (((r >> 21) % 32) == 7) { + if (InsecureRandBits(5) == 7) { int values[4]; - int num = 1 + (insecure_rand() % 4); + int num = 1 + (InsecureRandBits(2)); for (int k = 0; k < num; k++) { - values[k] = insecure_rand(); + values[k] = InsecureRand32(); } - test.insert_range(insecure_rand() % (test.size() + 1), values, values + num); + test.insert_range(InsecureRandRange(test.size() + 1), values, values + num); } - if (((r >> 26) % 32) == 8) { - int del = std::min(test.size(), 1 + (insecure_rand() % 4)); - int beg = insecure_rand() % (test.size() + 1 - del); + if (InsecureRandBits(5) == 8) { + int del = std::min(test.size(), 1 + (InsecureRandBits(2))); + int beg = InsecureRandRange(test.size() + 1 - del); test.erase(beg, beg + del); } - r = insecure_rand(); - if (r % 32 == 9) { - test.reserve(insecure_rand() % 32); + if (InsecureRandBits(5) == 9) { + test.reserve(InsecureRandBits(5)); } - if ((r >> 5) % 64 == 10) { + if (InsecureRandBits(6) == 10) { test.shrink_to_fit(); } if (test.size() > 0) { - test.update(insecure_rand() % test.size(), insecure_rand()); + test.update(InsecureRandRange(test.size()), InsecureRand32()); } - if (((r >> 11) % 1024) == 11) { + if (InsecureRandBits(10) == 11) { test.clear(); } - if (((r >> 21) % 512) == 12) { - test.assign(insecure_rand() % 32, insecure_rand()); + if (InsecureRandBits(9) == 12) { + test.assign(InsecureRandBits(5), InsecureRand32()); } - if (((r >> 15) % 8) == 3) { + if (InsecureRandBits(3) == 3) { test.swap(); } - if (((r >> 15) % 16) == 8) { + if (InsecureRandBits(4) == 8) { test.copy(); } - if (((r >> 15) % 32) == 18) { + if (InsecureRandBits(5) == 18) { test.move(); } } diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp index 2c8abc33f595..c4cec78d1114 100644 --- a/src/test/random_tests.cpp +++ b/src/test/random_tests.cpp @@ -25,14 +25,21 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests) BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.rand64(), ctx2.rand64()); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK(ctx1.randbytes(17) == ctx2.randbytes(17)); + BOOST_CHECK(ctx1.rand256() == ctx2.rand256()); BOOST_CHECK_EQUAL(ctx1.randbits(7), ctx2.randbits(7)); + BOOST_CHECK(ctx1.randbytes(128) == ctx2.randbytes(128)); BOOST_CHECK_EQUAL(ctx1.rand32(), ctx2.rand32()); BOOST_CHECK_EQUAL(ctx1.randbits(3), ctx2.randbits(3)); + BOOST_CHECK(ctx1.rand256() == ctx2.rand256()); + BOOST_CHECK(ctx1.randbytes(50) == ctx2.randbytes(50)); // Check that a nondeterministic ones are not FastRandomContext ctx3; FastRandomContext ctx4; BOOST_CHECK(ctx3.rand64() != ctx4.rand64()); // extremely unlikely to be equal + BOOST_CHECK(ctx3.rand256() != ctx4.rand256()); + BOOST_CHECK(ctx3.randbytes(7) != ctx4.randbytes(7)); } BOOST_AUTO_TEST_CASE(fastrandom_randbits) diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 89a731f567ce..2922d1cce9c8 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -11,7 +11,6 @@ #include "serialize.h" #include "streams.h" #include "test/test_dash.h" -#include "test/test_random.h" #include "util.h" #include "utilstrencodings.h" #include "version.h" @@ -90,30 +89,30 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un void static RandomScript(CScript &script) { static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR}; script = CScript(); - int ops = (insecure_rand() % 10); + int ops = (InsecureRandRange(10)); for (int i=0; i @@ -35,8 +34,8 @@ BOOST_AUTO_TEST_CASE(skiplist_test) } for (int i=0; i < 1000; i++) { - int from = insecure_rand() % (SKIPLIST_LENGTH - 1); - int to = insecure_rand() % (from + 1); + int from = InsecureRandRange(SKIPLIST_LENGTH - 1); + int to = InsecureRandRange(from + 1); BOOST_CHECK(vIndex[SKIPLIST_LENGTH - 1].GetAncestor(from) == &vIndex[from]); BOOST_CHECK(vIndex[from].GetAncestor(to) == &vIndex[to]); @@ -78,7 +77,7 @@ BOOST_AUTO_TEST_CASE(getlocator_test) // Test 100 random starting points for locators. for (int n=0; n<100; n++) { - int r = insecure_rand() % 150000; + int r = InsecureRandRange(150000); CBlockIndex* tip = (r < 100000) ? &vBlocksMain[r] : &vBlocksSide[r - 100000]; CBlockLocator locator = chain.GetLocator(tip); @@ -116,7 +115,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test) } else { // randomly choose something in the range [MTP, MTP*2] int64_t medianTimePast = vBlocksMain[i].GetMedianTimePast(); - int r = insecure_rand() % medianTimePast; + int r = InsecureRandRange(medianTimePast); vBlocksMain[i].nTime = r + medianTimePast; vBlocksMain[i].nTimeMax = std::max(vBlocksMain[i].nTime, vBlocksMain[i-1].nTimeMax); } @@ -135,7 +134,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test) // Verify that FindEarliestAtLeast is correct. for (unsigned int i=0; i<10000; ++i) { // Pick a random element in vBlocksMain. - int r = insecure_rand() % vBlocksMain.size(); + int r = InsecureRandRange(vBlocksMain.size()); int64_t test_time = vBlocksMain[r].nTime; CBlockIndex *ret = chain.FindEarliestAtLeast(test_time); BOOST_CHECK(ret->nTimeMax >= test_time); diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index 6a9984ef1c50..72060363d2ec 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -69,7 +69,7 @@ TestingSetup::TestingSetup(const std::string& chainName) : BasicTestingSetup(cha // instead of unit tests, but for now we need these here. RegisterAllCoreRPCCommands(tableRPC); ClearDatadirCache(); - pathTemp = GetTempPath() / strprintf("test_dash_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); + pathTemp = GetTempPath() / strprintf("test_dash_%lu_%i", (unsigned long)GetTime(), (int)(InsecureRandRange(100000))); fs::create_directories(pathTemp); gArgs.ForceSetArg("-datadir", pathTemp.string()); mempool.setSanityCheck(1.0); diff --git a/src/test/test_dash.h b/src/test/test_dash.h index eef7dc9ff6d0..c5babca70c91 100644 --- a/src/test/test_dash.h +++ b/src/test/test_dash.h @@ -10,11 +10,32 @@ #include "fs.h" #include "key.h" #include "pubkey.h" +#include "random.h" #include "txdb.h" #include "txmempool.h" #include +extern uint256 insecure_rand_seed; +extern FastRandomContext insecure_rand_ctx; + +static inline void SeedInsecureRand(bool fDeterministic = false) +{ + if (fDeterministic) { + insecure_rand_seed = uint256(); + } else { + insecure_rand_seed = GetRandHash(); + } + insecure_rand_ctx = FastRandomContext(insecure_rand_seed); +} + +static inline uint32_t InsecureRand32() { return insecure_rand_ctx.rand32(); } +static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); } +static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); } +static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); } +static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); } +static inline std::vector InsecureRandBytes(size_t len) { return insecure_rand_ctx.randbytes(len); } + /** Basic testing setup. * This just configures logging and chain parameters. */ diff --git a/src/test/test_random.h b/src/test/test_random.h deleted file mode 100644 index d1fae70458c7..000000000000 --- a/src/test/test_random.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_TEST_RANDOM_H -#define BITCOIN_TEST_RANDOM_H - -#include "random.h" - -extern uint256 insecure_rand_seed; -extern FastRandomContext insecure_rand_ctx; - -static inline void seed_insecure_rand(bool fDeterministic = false) -{ - if (fDeterministic) { - insecure_rand_seed = uint256(); - } else { - insecure_rand_seed = GetRandHash(); - } - insecure_rand_ctx = FastRandomContext(insecure_rand_seed); -} - -static inline uint32_t insecure_rand(void) -{ - return insecure_rand_ctx.rand32(); -} - -#endif diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 45c8de288130..77d879de5922 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -10,7 +10,6 @@ #include "utilstrencodings.h" #include "utilmoneystr.h" #include "test/test_dash.h" -#include "test/test_random.h" #include #include @@ -256,7 +255,7 @@ BOOST_AUTO_TEST_CASE(util_IsHex) BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) { - seed_insecure_rand(true); + SeedInsecureRand(true); for (int mod=2;mod<11;mod++) { int mask = 1; @@ -270,7 +269,7 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand) for (int i = 0; i < 10000; i++) { uint32_t rval; do{ - rval=insecure_rand()&mask; + rval=InsecureRand32()&mask; }while(rval>=(uint32_t)mod); count += rval==0; } diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index cce36941d8cd..33e4c85f8b3a 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -5,7 +5,6 @@ #include "chain.h" #include "versionbits.h" #include "test/test_dash.h" -#include "test/test_random.h" #include "chainparams.h" #include "validation.h" #include "consensus/params.h" @@ -81,7 +80,7 @@ class VersionBitsTester VersionBitsTester& TestStateSinceHeight(int height) { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? NULL : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num)); } } @@ -91,7 +90,7 @@ class VersionBitsTester VersionBitsTester& TestDefined() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_DEFINED, strprintf("Test %i for DEFINED", num)); } } @@ -101,7 +100,7 @@ class VersionBitsTester VersionBitsTester& TestStarted() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_STARTED, strprintf("Test %i for STARTED", num)); } } @@ -111,7 +110,7 @@ class VersionBitsTester VersionBitsTester& TestLockedIn() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_LOCKED_IN, strprintf("Test %i for LOCKED_IN", num)); } } @@ -121,7 +120,7 @@ class VersionBitsTester VersionBitsTester& TestActive() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_ACTIVE, strprintf("Test %i for ACTIVE", num)); } } @@ -131,7 +130,7 @@ class VersionBitsTester VersionBitsTester& TestFailed() { for (int i = 0; i < CHECKERS; i++) { - if ((insecure_rand() & ((1 << i) - 1)) == 0) { + if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? NULL : vpblock.back()) == THRESHOLD_FAILED, strprintf("Test %i for FAILED", num)); } } diff --git a/src/wallet/test/crypto_tests.cpp b/src/wallet/test/crypto_tests.cpp index af93d0856ea7..696fa934a332 100644 --- a/src/wallet/test/crypto_tests.cpp +++ b/src/wallet/test/crypto_tests.cpp @@ -2,9 +2,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "test/test_random.h" -#include "utilstrencodings.h" #include "test/test_dash.h" +#include "utilstrencodings.h" #include "wallet/crypter.h" #include @@ -283,7 +282,7 @@ BOOST_AUTO_TEST_CASE(passphrase) { std::string hash(GetRandHash().ToString()); std::vector vchSalt(8); GetRandBytes(&vchSalt[0], vchSalt.size()); - uint32_t rounds = insecure_rand(); + uint32_t rounds = InsecureRand32(); if (rounds > 30000) rounds = 30000; TestCrypter::TestPassphrase(vchSalt, SecureString(hash.begin(), hash.end()), rounds); From 6318ca6367bfb2d0690e5e3c2227466d34b1c96e Mon Sep 17 00:00:00 2001 From: Pasta Date: Thu, 4 Jul 2019 23:36:48 -0500 Subject: [PATCH 350/987] insecure_rand() -> InsecureRandBits Signed-off-by: Pasta --- src/test/coins_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 22cb2ca44b18..09771e241ba2 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -145,8 +145,8 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) // Determine whether to test HaveCoin before or after Access* (or both). As these functions // can influence each other's behaviour by pulling things into the cache, all combinations // are tested. - bool test_havecoin_before = (insecure_rand() & 0x3) == 0; // TODO change to InsecureRandBits(2) when backporting Bitcoin #10321 - bool test_havecoin_after = (insecure_rand() & 0x3) == 0; // TODO change to InsecureRandBits(2) when backporting Bitcoin #10321 + bool test_havecoin_before = (InsecureRandBits(2)) == 0; + bool test_havecoin_after = (InsecureRandBits(2)) == 0; bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false; const Coin& entry = (InsecureRandRange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0)); From 20e30fb93c8ec21c11dc64db8ee103fd35e08dbd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 8 Jun 2017 09:43:03 +0200 Subject: [PATCH 351/987] Merge #10524: [tests] Remove printf(...) 0abc588 [tests] Remove printf(...) (practicalswift) Tree-SHA512: a56fa1edce050f5a44a53842223fc99e4e8ade413047e04f2064faeb5c4a418864a94471853d5c26a20608d1dcc18b9226d7fe15172f79a66cc5cf6e1443f7e9 --- src/test/sighash_tests.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 2922d1cce9c8..d6f6342a657d 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -29,7 +29,6 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); if (nIn >= txTo.vin.size()) { - printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn); return one; } CMutableTransaction txTmp(txTo); @@ -60,7 +59,6 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un unsigned int nOut = nIn; if (nOut >= txTmp.vout.size()) { - printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut); return one; } txTmp.vout.resize(nOut+1); From b6dc579be8cea312b9a35a6ba67cdc15870d66fd Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 8 Jun 2017 12:34:53 +0200 Subject: [PATCH 352/987] Merge #10547: [tests] Use FastRandomContext instead of boost::random::{mt19937,uniform_int_distribution} 227ae9b [tests] Use FastRandomContext instead of boost::random::{mt19937,uniform_int_distribution} (practicalswift) Tree-SHA512: 1bde6c8b9498051fa2eae4913eb1f5411adea8dea1511c0df859aea57a2a7db6f5839945ddf2eccdddfa322bceacad35a5d875742db7d15e40dbea83185307bb --- src/test/scheduler_tests.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/test/scheduler_tests.cpp b/src/test/scheduler_tests.cpp index 8a9378179d5c..149b8902046a 100644 --- a/src/test/scheduler_tests.cpp +++ b/src/test/scheduler_tests.cpp @@ -8,8 +8,6 @@ #include "test/test_dash.h" #include -#include -#include #include #include @@ -56,10 +54,10 @@ BOOST_AUTO_TEST_CASE(manythreads) boost::mutex counterMutex[10]; int counter[10] = { 0 }; - boost::random::mt19937 rng(42); - boost::random::uniform_int_distribution<> zeroToNine(0, 9); - boost::random::uniform_int_distribution<> randomMsec(-11, 1000); - boost::random::uniform_int_distribution<> randomDelta(-1000, 1000); + FastRandomContext rng(42); + auto zeroToNine = [](FastRandomContext& rc) -> int { return rc.randrange(10); }; // [0, 9] + auto randomMsec = [](FastRandomContext& rc) -> int { return -11 + rc.randrange(1012); }; // [-11, 1000] + auto randomDelta = [](FastRandomContext& rc) -> int { return -1000 + rc.randrange(2001); }; // [-1000, 1000] boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now(); boost::chrono::system_clock::time_point now = start; From 7e7c3ce6ca367d9ca6f0f5d645b61dd85dd899d7 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 8 Jun 2017 12:45:27 +0200 Subject: [PATCH 353/987] Merge #10548: Use std::unordered_{map,set} (C++11) instead of boost::unordered_{map,set} 246a02f Use std::unordered_{map,set} (C++11) instead of boost::unordered_{map,set} (practicalswift) Tree-SHA512: 35cd42012248174751e4b87efbc78689957f731d7710dea7e369974c6ec31b15b32d1537fb0d875c94c7ffb5046d9784735e218e5baeed96d525861dab6d4252 --- src/memusage.h | 16 ---------------- src/validation.h | 4 +--- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/memusage.h b/src/memusage.h index 19e2e8bab5a7..d73b1f937d51 100644 --- a/src/memusage.h +++ b/src/memusage.h @@ -16,8 +16,6 @@ #include #include -#include -#include namespace memusage { @@ -148,8 +146,6 @@ static inline size_t DynamicUsage(const std::shared_ptr& p) return p ? MallocUsage(sizeof(X)) + MallocUsage(sizeof(stl_shared_counter)) : 0; } -// Boost data structures - template struct unordered_node : private X { @@ -157,18 +153,6 @@ struct unordered_node : private X void* ptr; }; -template -static inline size_t DynamicUsage(const boost::unordered_set& s) -{ - return MallocUsage(sizeof(unordered_node)) * s.size() + MallocUsage(sizeof(void*) * s.bucket_count()); -} - -template -static inline size_t DynamicUsage(const boost::unordered_map& m) -{ - return MallocUsage(sizeof(unordered_node >)) * m.size() + MallocUsage(sizeof(void*) * m.bucket_count()); -} - template static inline size_t DynamicUsage(const std::unordered_set& s) { diff --git a/src/validation.h b/src/validation.h index 0875fdc59fe4..ade1a3cd3fc9 100644 --- a/src/validation.h +++ b/src/validation.h @@ -32,8 +32,6 @@ #include -#include - class CBlockIndex; class CBlockTreeDB; class CBloomFilter; @@ -162,7 +160,7 @@ extern CScript COINBASE_FLAGS; extern CCriticalSection cs_main; extern CBlockPolicyEstimator feeEstimator; extern CTxMemPool mempool; -typedef boost::unordered_map BlockMap; +typedef std::unordered_map BlockMap; typedef std::unordered_multimap PrevBlockMap; extern BlockMap mapBlockIndex; extern PrevBlockMap mapPrevBlockIndex; From b92d2dd66ae23028421da539795e7fdb89a87ced Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 8 Jun 2017 19:35:28 +0200 Subject: [PATCH 354/987] Merge #10545: Use list initialization (C++11) for maps/vectors instead of boost::assign::map_list_of/list_of 3fb81a8 Use list initialization (C++11) for maps/vectors instead of boost::assign::map_list_of/list_of (practicalswift) Tree-SHA512: 63a9ac9ec5799472943dce1cd92a4b14e7f1fe12758a5fc4b1efceaf2c85a4ba71dad5ccc50813527f18b192e7714c076e2478ecd6ca0d452b24e88416f872f7 --- src/chainparams.cpp | 79 +++++++++++++++++----------------- src/core_read.cpp | 1 - src/core_write.cpp | 18 ++++---- src/dash-tx.cpp | 7 ++- src/qt/coincontroldialog.cpp | 2 - src/rpc/mining.cpp | 6 +-- src/rpc/misc.cpp | 3 +- src/rpc/rawtransaction.cpp | 29 ++++++------- src/test/DoS_tests.cpp | 1 - src/test/crypto_tests.cpp | 1 - src/test/netbase_tests.cpp | 25 ++++++----- src/test/pmt_tests.cpp | 18 ++++---- src/test/rpc_tests.cpp | 9 ++-- src/test/transaction_tests.cpp | 31 +++++++------ src/wallet/rpcdump.cpp | 3 +- src/wallet/rpcwallet.cpp | 10 ++--- 16 files changed, 114 insertions(+), 129 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index da0002bfc8d4..dc99294368e7 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -15,8 +15,6 @@ #include -#include - #include "chainparamsseeds.h" static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward) @@ -329,9 +327,9 @@ class CMainParams : public CChainParams { // Dash private keys start with '7' or 'X' base58Prefixes[SECRET_KEY] = std::vector(1,204); // Dash BIP32 pubkeys start with 'xpub' (Bitcoin defaults) - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container >(); + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E}; // Dash BIP32 prvkeys start with 'xprv' (Bitcoin defaults) - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4}; // Dash BIP44 coin type is '5' nExtCoinType = 5; @@ -361,31 +359,32 @@ class CMainParams : public CChainParams { fBIP9CheckMasternodesUpgraded = true; checkpointData = (CCheckpointData) { - boost::assign::map_list_of - ( 1500, uint256S("0x000000aaf0300f59f49bc3e970bad15c11f961fe2347accffff19d96ec9778e3")) - ( 4991, uint256S("0x000000003b01809551952460744d5dbb8fcbd6cbae3c220267bf7fa43f837367")) - ( 9918, uint256S("0x00000000213e229f332c0ffbe34defdaa9e74de87f2d8d1f01af8d121c3c170b")) - ( 16912, uint256S("0x00000000075c0d10371d55a60634da70f197548dbbfa4123e12abfcbc5738af9")) - ( 23912, uint256S("0x0000000000335eac6703f3b1732ec8b2f89c3ba3a7889e5767b090556bb9a276")) - ( 35457, uint256S("0x0000000000b0ae211be59b048df14820475ad0dd53b9ff83b010f71a77342d9f")) - ( 45479, uint256S("0x000000000063d411655d590590e16960f15ceea4257122ac430c6fbe39fbf02d")) - ( 55895, uint256S("0x0000000000ae4c53a43639a4ca027282f69da9c67ba951768a20415b6439a2d7")) - ( 68899, uint256S("0x0000000000194ab4d3d9eeb1f2f792f21bb39ff767cb547fe977640f969d77b7")) - ( 74619, uint256S("0x000000000011d28f38f05d01650a502cc3f4d0e793fbc26e2a2ca71f07dc3842")) - ( 75095, uint256S("0x0000000000193d12f6ad352a9996ee58ef8bdc4946818a5fec5ce99c11b87f0d")) - ( 88805, uint256S("0x00000000001392f1652e9bf45cd8bc79dc60fe935277cd11538565b4a94fa85f")) - ( 107996, uint256S("0x00000000000a23840ac16115407488267aa3da2b9bc843e301185b7d17e4dc40")) - ( 137993, uint256S("0x00000000000cf69ce152b1bffdeddc59188d7a80879210d6e5c9503011929c3c")) - ( 167996, uint256S("0x000000000009486020a80f7f2cc065342b0c2fb59af5e090cd813dba68ab0fed")) - ( 207992, uint256S("0x00000000000d85c22be098f74576ef00b7aa00c05777e966aff68a270f1e01a5")) - ( 312645, uint256S("0x0000000000059dcb71ad35a9e40526c44e7aae6c99169a9e7017b7d84b1c2daf")) - ( 407452, uint256S("0x000000000003c6a87e73623b9d70af7cd908ae22fee466063e4ffc20be1d2dbc")) - ( 523412, uint256S("0x000000000000e54f036576a10597e0e42cc22a5159ce572f999c33975e121d4d")) - ( 523930, uint256S("0x0000000000000bccdb11c2b1cfb0ecab452abf267d89b7f46eaf2d54ce6e652c")) - ( 750000, uint256S("0x00000000000000b4181bbbdddbae464ce11fede5d0292fb63fdede1e7c8ab21c")) - ( 888900, uint256S("0x0000000000000026c29d576073ab51ebd1d3c938de02e9a44c7ee9e16f82db28")) - ( 967800, uint256S("0x0000000000000024e26c7df7e46d673724d223cf4ca2b2adc21297cc095600f4")) - ( 1067570, uint256S("0x000000000000001e09926bcf5fa4513d23e870a34f74e38200db99eb3f5b7a70")) + { + {1500, uint256S("0x000000aaf0300f59f49bc3e970bad15c11f961fe2347accffff19d96ec9778e3")}, + {4991, uint256S("0x000000003b01809551952460744d5dbb8fcbd6cbae3c220267bf7fa43f837367")}, + {9918, uint256S("0x00000000213e229f332c0ffbe34defdaa9e74de87f2d8d1f01af8d121c3c170b")}, + {16912, uint256S("0x00000000075c0d10371d55a60634da70f197548dbbfa4123e12abfcbc5738af9")}, + {23912, uint256S("0x0000000000335eac6703f3b1732ec8b2f89c3ba3a7889e5767b090556bb9a276")}, + {35457, uint256S("0x0000000000b0ae211be59b048df14820475ad0dd53b9ff83b010f71a77342d9f")}, + {45479, uint256S("0x000000000063d411655d590590e16960f15ceea4257122ac430c6fbe39fbf02d")}, + {55895, uint256S("0x0000000000ae4c53a43639a4ca027282f69da9c67ba951768a20415b6439a2d7")}, + {68899, uint256S("0x0000000000194ab4d3d9eeb1f2f792f21bb39ff767cb547fe977640f969d77b7")}, + {74619, uint256S("0x000000000011d28f38f05d01650a502cc3f4d0e793fbc26e2a2ca71f07dc3842")}, + {75095, uint256S("0x0000000000193d12f6ad352a9996ee58ef8bdc4946818a5fec5ce99c11b87f0d")}, + {88805, uint256S("0x00000000001392f1652e9bf45cd8bc79dc60fe935277cd11538565b4a94fa85f")}, + {107996, uint256S("0x00000000000a23840ac16115407488267aa3da2b9bc843e301185b7d17e4dc40")}, + {137993, uint256S("0x00000000000cf69ce152b1bffdeddc59188d7a80879210d6e5c9503011929c3c")}, + {167996, uint256S("0x000000000009486020a80f7f2cc065342b0c2fb59af5e090cd813dba68ab0fed")}, + {207992, uint256S("0x00000000000d85c22be098f74576ef00b7aa00c05777e966aff68a270f1e01a5")}, + {312645, uint256S("0x0000000000059dcb71ad35a9e40526c44e7aae6c99169a9e7017b7d84b1c2daf")}, + {407452, uint256S("0x000000000003c6a87e73623b9d70af7cd908ae22fee466063e4ffc20be1d2dbc")}, + {523412, uint256S("0x000000000000e54f036576a10597e0e42cc22a5159ce572f999c33975e121d4d")}, + {523930, uint256S("0x0000000000000bccdb11c2b1cfb0ecab452abf267d89b7f46eaf2d54ce6e652c")}, + {750000, uint256S("0x00000000000000b4181bbbdddbae464ce11fede5d0292fb63fdede1e7c8ab21c")}, + {888900, uint256S("0x0000000000000026c29d576073ab51ebd1d3c938de02e9a44c7ee9e16f82db28")}, + {967800, uint256S("0x0000000000000024e26c7df7e46d673724d223cf4ca2b2adc21297cc095600f4")}, + {1067570, uint256S("0x000000000000001e09926bcf5fa4513d23e870a34f74e38200db99eb3f5b7a70")}, + } }; chainTxData = ChainTxData{ @@ -508,9 +507,9 @@ class CTestNetParams : public CChainParams { // Testnet private keys start with '9' or 'c' (Bitcoin defaults) base58Prefixes[SECRET_KEY] = std::vector(1,239); // Testnet Dash BIP32 pubkeys start with 'tpub' (Bitcoin defaults) - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; // Testnet Dash BIP32 prvkeys start with 'tprv' (Bitcoin defaults) - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; // Testnet Dash BIP44 coin type is '1' (All coin's testnet default) nExtCoinType = 1; @@ -694,9 +693,10 @@ class CDevNetParams : public CChainParams { fBIP9CheckMasternodesUpgraded = false; checkpointData = (CCheckpointData) { - boost::assign::map_list_of - ( 0, uint256S("0x000008ca1832a4baf228eb1553c03d3a2c8e02399550dd6ea8d65cec3ef23d2e")) - ( 1, devnetGenesis.GetHash()) + { + { 0, uint256S("0x000008ca1832a4baf228eb1553c03d3a2c8e02399550dd6ea8d65cec3ef23d2e")}, + { 1, devnetGenesis.GetHash() }, + } }; chainTxData = ChainTxData{ @@ -818,9 +818,10 @@ class CRegTestParams : public CChainParams { // regtest usually has no masternodes in most tests, so don't check for upgraged MNs fBIP9CheckMasternodesUpgraded = false; - checkpointData = (CCheckpointData){ - boost::assign::map_list_of - ( 0, uint256S("0x000008ca1832a4baf228eb1553c03d3a2c8e02399550dd6ea8d65cec3ef23d2e")) + checkpointData = (CCheckpointData) { + { + {0, uint256S("0x000008ca1832a4baf228eb1553c03d3a2c8e02399550dd6ea8d65cec3ef23d2e")}, + } }; chainTxData = ChainTxData{ @@ -836,9 +837,9 @@ class CRegTestParams : public CChainParams { // Regtest private keys start with '9' or 'c' (Bitcoin defaults) base58Prefixes[SECRET_KEY] = std::vector(1,239); // Regtest Dash BIP32 pubkeys start with 'tpub' (Bitcoin defaults) - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; // Regtest Dash BIP32 prvkeys start with 'tprv' (Bitcoin defaults) - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; // Regtest Dash BIP44 coin type is '1' (All coin's testnet default) nExtCoinType = 1; diff --git a/src/core_read.cpp b/src/core_read.cpp index ba6677a8131a..f6bac8cde0cb 100644 --- a/src/core_read.cpp +++ b/src/core_read.cpp @@ -18,7 +18,6 @@ #include #include #include -#include CScript ParseScript(const std::string& s) { diff --git a/src/core_write.cpp b/src/core_write.cpp index 113c57ff34ee..702f9b413ae7 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -22,7 +22,6 @@ #include "evo/specialtx.h" #include "llmq/quorums_commitment.h" -#include #include std::string FormatScript(const CScript& script) @@ -60,15 +59,14 @@ std::string FormatScript(const CScript& script) return ret.substr(0, ret.size() - 1); } -const std::map mapSigHashTypes = - boost::assign::map_list_of - (static_cast(SIGHASH_ALL), std::string("ALL")) - (static_cast(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")) - (static_cast(SIGHASH_NONE), std::string("NONE")) - (static_cast(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")) - (static_cast(SIGHASH_SINGLE), std::string("SINGLE")) - (static_cast(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")) - ; +const std::map mapSigHashTypes = { + {static_cast(SIGHASH_ALL), std::string("ALL")}, + {static_cast(SIGHASH_ALL|SIGHASH_ANYONECANPAY), std::string("ALL|ANYONECANPAY")}, + {static_cast(SIGHASH_NONE), std::string("NONE")}, + {static_cast(SIGHASH_NONE|SIGHASH_ANYONECANPAY), std::string("NONE|ANYONECANPAY")}, + {static_cast(SIGHASH_SINGLE), std::string("SINGLE")}, + {static_cast(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY), std::string("SINGLE|ANYONECANPAY")}, +}; /** * Create the assembly string representation of a CScript object. diff --git a/src/dash-tx.cpp b/src/dash-tx.cpp index 6b68e704edb4..ee29754160ef 100644 --- a/src/dash-tx.cpp +++ b/src/dash-tx.cpp @@ -24,7 +24,6 @@ #include #include -#include #include "stacktraces.h" @@ -521,7 +520,11 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) if (!prevOut.isObject()) throw std::runtime_error("expected prevtxs internal object"); - std::map types = boost::assign::map_list_of("txid", UniValue::VSTR)("vout",UniValue::VNUM)("scriptPubKey",UniValue::VSTR); + std::map types = { + {"txid", UniValue::VSTR}, + {"vout", UniValue::VNUM}, + {"scriptPubKey", UniValue::VSTR}, + }; if (!prevOut.checkObject(types)) throw std::runtime_error("prevtxs internal object typecheck fail"); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 9cdfaddf0912..ab8ee15376fc 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -24,8 +24,6 @@ #include "instantsend.h" #include "privatesend/privatesend-client.h" -#include // for 'map_list_of()' - #include #include #include diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 85efec369c1b..64c0fdb0672a 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -37,8 +37,6 @@ #include #include -#include - #include /** @@ -846,7 +844,7 @@ UniValue estimatefee(const JSONRPCRequest& request) + HelpExampleCli("estimatefee", "6") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, {UniValue::VNUM}); int nBlocks = request.params[0].get_int(); if (nBlocks < 1) @@ -883,7 +881,7 @@ UniValue estimatesmartfee(const JSONRPCRequest& request) + HelpExampleCli("estimatesmartfee", "6") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, {UniValue::VNUM}); int nBlocks = request.params[0].get_int(); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 1f0aa119d510..c8d6ef003a42 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -32,7 +32,6 @@ #include #endif -#include #include #include @@ -634,7 +633,7 @@ UniValue setmocktime(const JSONRPCRequest& request) // ensure all call sites of GetTime() are accessing this safely. LOCK(cs_main); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VNUM)); + RPCTypeCheck(request.params, {UniValue::VNUM}); SetMockTime(request.params[0].get_int64()); return NullUniValue; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index b993c3818526..72c6a8eb0a2d 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -40,8 +40,6 @@ #include -#include - #include @@ -379,7 +377,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) + HelpExampleRpc("createrawtransaction", "\"[{\\\"txid\\\":\\\"myid\\\",\\\"vout\\\":0}]\", \"{\\\"data\\\":\\\"00010203\\\"}\"") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)(UniValue::VNUM), true); + RPCTypeCheck(request.params, {UniValue::VARR, UniValue::VOBJ, UniValue::VNUM}, true); if (request.params[0].isNull() || request.params[1].isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, arguments 1 and 2 must be non-null"); @@ -510,7 +508,7 @@ UniValue decoderawtransaction(const JSONRPCRequest& request) ); LOCK(cs_main); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, {UniValue::VSTR}); CMutableTransaction mtx; @@ -548,7 +546,7 @@ UniValue decodescript(const JSONRPCRequest& request) + HelpExampleRpc("decodescript", "\"hexstring\"") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, {UniValue::VSTR}); UniValue r(UniValue::VOBJ); CScript script; @@ -654,7 +652,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) #else LOCK(cs_main); #endif - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VARR)(UniValue::VARR)(UniValue::VSTR), true); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR, UniValue::VARR, UniValue::VSTR}, true); std::vector txData(ParseHexV(request.params[0], "argument 1")); CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION); @@ -786,15 +784,14 @@ UniValue signrawtransaction(const JSONRPCRequest& request) int nHashType = SIGHASH_ALL; if (request.params.size() > 3 && !request.params[3].isNull()) { - static std::map mapSigHashValues = - boost::assign::map_list_of - (std::string("ALL"), int(SIGHASH_ALL)) - (std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)) - (std::string("NONE"), int(SIGHASH_NONE)) - (std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)) - (std::string("SINGLE"), int(SIGHASH_SINGLE)) - (std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)) - ; + static std::map mapSigHashValues = { + {std::string("ALL"), int(SIGHASH_ALL)}, + {std::string("ALL|ANYONECANPAY"), int(SIGHASH_ALL|SIGHASH_ANYONECANPAY)}, + {std::string("NONE"), int(SIGHASH_NONE)}, + {std::string("NONE|ANYONECANPAY"), int(SIGHASH_NONE|SIGHASH_ANYONECANPAY)}, + {std::string("SINGLE"), int(SIGHASH_SINGLE)}, + {std::string("SINGLE|ANYONECANPAY"), int(SIGHASH_SINGLE|SIGHASH_ANYONECANPAY)}, + }; std::string strHashType = request.params[3].get_str(); if (mapSigHashValues.count(strHashType)) nHashType = mapSigHashValues[strHashType]; @@ -874,7 +871,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) ); LOCK(cs_main); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)(UniValue::VBOOL)); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL, UniValue::VBOOL}); // parse hex string from parameter CMutableTransaction mtx; diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 7db06e2f1ee5..9ce9688ebb41 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -18,7 +18,6 @@ #include -#include // for 'map_list_of()' #include #include #include diff --git a/src/test/crypto_tests.cpp b/src/test/crypto_tests.cpp index e3171107d645..a72482e4acc5 100644 --- a/src/test/crypto_tests.cpp +++ b/src/test/crypto_tests.cpp @@ -16,7 +16,6 @@ #include -#include #include #include #include diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp index 4fe47f937a4d..a7ba36819448 100644 --- a/src/test/netbase_tests.cpp +++ b/src/test/netbase_tests.cpp @@ -8,7 +8,6 @@ #include -#include #include BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup) @@ -270,18 +269,18 @@ BOOST_AUTO_TEST_CASE(subnet_test) BOOST_AUTO_TEST_CASE(netbase_getgroup) { - BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == boost::assign::list_of(0)); // Local -> !Routable() - BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == boost::assign::list_of(0)); // !Valid -> !Routable() - BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == boost::assign::list_of(0)); // RFC1918 -> !Routable() - BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == boost::assign::list_of(0)); // RFC3927 -> !Routable() - BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // IPv4 - BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6145 - BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC6052 - BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC3964 - BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV4)(1)(2)); // RFC4380 - BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == boost::assign::list_of((unsigned char)NET_TOR)(239)); // Tor - BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(4)(112)(175)); //he.net - BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == boost::assign::list_of((unsigned char)NET_IPV6)(32)(1)(32)(1)); //IPv6 + BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == std::vector({0})); // Local -> !Routable() + BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == std::vector({0})); // !Valid -> !Routable() + BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == std::vector({0})); // RFC1918 -> !Routable() + BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == std::vector({0})); // RFC3927 -> !Routable() + BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == std::vector({(unsigned char)NET_IPV4, 1, 2})); // IPv4 + BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() == std::vector({(unsigned char)NET_IPV4, 1, 2})); // RFC6145 + BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() == std::vector({(unsigned char)NET_IPV4, 1, 2})); // RFC6052 + BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() == std::vector({(unsigned char)NET_IPV4, 1, 2})); // RFC3964 + BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() == std::vector({(unsigned char)NET_IPV4, 1, 2})); // RFC4380 + BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() == std::vector({(unsigned char)NET_TOR, 239})); // Tor + BOOST_CHECK(ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() == std::vector({(unsigned char)NET_IPV6, 32, 1, 4, 112, 175})); //he.net + BOOST_CHECK(ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() == std::vector({(unsigned char)NET_IPV6, 32, 1, 32, 1})); //IPv6 } diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index aa672d563f43..2ed7328bfca2 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -13,7 +13,6 @@ #include -#include #include class CPartialMerkleTreeTester : public CPartialMerkleTree @@ -109,14 +108,15 @@ BOOST_AUTO_TEST_CASE(pmt_test1) BOOST_AUTO_TEST_CASE(pmt_malleability) { - std::vector vTxid = boost::assign::list_of - (ArithToUint256(1))(ArithToUint256(2)) - (ArithToUint256(3))(ArithToUint256(4)) - (ArithToUint256(5))(ArithToUint256(6)) - (ArithToUint256(7))(ArithToUint256(8)) - (ArithToUint256(9))(ArithToUint256(10)) - (ArithToUint256(9))(ArithToUint256(10)); - std::vector vMatch = boost::assign::list_of(false)(false)(false)(false)(false)(false)(false)(false)(false)(true)(true)(false); + std::vector vTxid = { + ArithToUint256(1), ArithToUint256(2), + ArithToUint256(3), ArithToUint256(4), + ArithToUint256(5), ArithToUint256(6), + ArithToUint256(7), ArithToUint256(8), + ArithToUint256(9), ArithToUint256(10), + ArithToUint256(9), ArithToUint256(10), + }; + std::vector vMatch = {false, false, false, false, false, false, false, false, false, true, true, false}; CPartialMerkleTree tree(vTxid, vMatch); std::vector vIndex; diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index af2f0812a64d..cb1020705e20 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -11,7 +11,6 @@ #include "test/test_dash.h" #include -#include #include #include @@ -325,20 +324,20 @@ BOOST_AUTO_TEST_CASE(rpc_convert_values_generatetoaddress) { UniValue result; - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("yhq7ifNCtTKEpY4Yu5XPCcztQco6Fh6JsZ"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "yhq7ifNCtTKEpY4Yu5XPCcztQco6Fh6JsZ"})); BOOST_CHECK_EQUAL(result[0].get_int(), 101); BOOST_CHECK_EQUAL(result[1].get_str(), "yhq7ifNCtTKEpY4Yu5XPCcztQco6Fh6JsZ"); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("101")("yTretFTpoi3oQ3maZk5QadGaDWPiKnmDBc"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"101", "yTretFTpoi3oQ3maZk5QadGaDWPiKnmDBc"})); BOOST_CHECK_EQUAL(result[0].get_int(), 101); BOOST_CHECK_EQUAL(result[1].get_str(), "yTretFTpoi3oQ3maZk5QadGaDWPiKnmDBc"); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("yNbNZyCiTYSFtDwEXt7jChV7tZVYX862ua")("9"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "yNbNZyCiTYSFtDwEXt7jChV7tZVYX862ua", "9"})); BOOST_CHECK_EQUAL(result[0].get_int(), 1); BOOST_CHECK_EQUAL(result[1].get_str(), "yNbNZyCiTYSFtDwEXt7jChV7tZVYX862ua"); BOOST_CHECK_EQUAL(result[2].get_int(), 9); - BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", boost::assign::list_of("1")("yTG8jLL3MvteKXgbEcHyaN7JvTPCejQpSh")("9"))); + BOOST_CHECK_NO_THROW(result = RPCConvertValues("generatetoaddress", {"1", "yTG8jLL3MvteKXgbEcHyaN7JvTPCejQpSh", "9"})); BOOST_CHECK_EQUAL(result[0].get_int(), 1); BOOST_CHECK_EQUAL(result[1].get_str(), "yTG8jLL3MvteKXgbEcHyaN7JvTPCejQpSh"); BOOST_CHECK_EQUAL(result[2].get_int(), 9); diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 3afe38f8affd..9681111828e1 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -23,29 +23,28 @@ #include #include -#include #include -#include #include // In script_tests.cpp extern UniValue read_json(const std::string& jsondata); -static std::map mapFlagNames = boost::assign::map_list_of - (std::string("NONE"), (unsigned int)SCRIPT_VERIFY_NONE) - (std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH) - (std::string("STRICTENC"), (unsigned int)SCRIPT_VERIFY_STRICTENC) - (std::string("DERSIG"), (unsigned int)SCRIPT_VERIFY_DERSIG) - (std::string("LOW_S"), (unsigned int)SCRIPT_VERIFY_LOW_S) - (std::string("SIGPUSHONLY"), (unsigned int)SCRIPT_VERIFY_SIGPUSHONLY) - (std::string("MINIMALDATA"), (unsigned int)SCRIPT_VERIFY_MINIMALDATA) - (std::string("NULLDUMMY"), (unsigned int)SCRIPT_VERIFY_NULLDUMMY) - (std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int)SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) - (std::string("CLEANSTACK"), (unsigned int)SCRIPT_VERIFY_CLEANSTACK) - (std::string("NULLFAIL"), (unsigned int)SCRIPT_VERIFY_NULLFAIL) - (std::string("CHECKLOCKTIMEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY) - (std::string("CHECKSEQUENCEVERIFY"), (unsigned int)SCRIPT_VERIFY_CHECKSEQUENCEVERIFY); +static std::map mapFlagNames = { + {std::string("NONE"), (unsigned int) SCRIPT_VERIFY_NONE}, + {std::string("P2SH"), (unsigned int) SCRIPT_VERIFY_P2SH}, + {std::string("STRICTENC"), (unsigned int) SCRIPT_VERIFY_STRICTENC}, + {std::string("DERSIG"), (unsigned int) SCRIPT_VERIFY_DERSIG}, + {std::string("LOW_S"), (unsigned int) SCRIPT_VERIFY_LOW_S}, + {std::string("SIGPUSHONLY"), (unsigned int) SCRIPT_VERIFY_SIGPUSHONLY}, + {std::string("MINIMALDATA"), (unsigned int) SCRIPT_VERIFY_MINIMALDATA}, + {std::string("NULLDUMMY"), (unsigned int) SCRIPT_VERIFY_NULLDUMMY}, + {std::string("DISCOURAGE_UPGRADABLE_NOPS"), (unsigned int) SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS}, + {std::string("CLEANSTACK"), (unsigned int) SCRIPT_VERIFY_CLEANSTACK}, + {std::string("NULLFAIL"), (unsigned int) SCRIPT_VERIFY_NULLFAIL}, + {std::string("CHECKLOCKTIMEVERIFY"), (unsigned int) SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY}, + {std::string("CHECKSEQUENCEVERIFY"), (unsigned int) SCRIPT_VERIFY_CHECKSEQUENCEVERIFY}, +}; unsigned int ParseScriptFlags(std::string strFlags) { diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 5d30d4cab064..8b5ccb97cd1e 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -27,7 +27,6 @@ #include -#include #include std::string static EncodeDumpTime(int64_t nTime) { @@ -1276,7 +1275,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) // clang-format on - RPCTypeCheck(mainRequest.params, boost::assign::list_of(UniValue::VARR)(UniValue::VOBJ)); + RPCTypeCheck(mainRequest.params, {UniValue::VARR, UniValue::VOBJ}); const UniValue& requests = mainRequest.params[0]; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 128bfbfc5920..70185800c236 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -30,8 +30,6 @@ #include -#include - #include CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request) @@ -2313,9 +2311,9 @@ UniValue lockunspent(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); if (request.params.size() == 1) - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL)); + RPCTypeCheck(request.params, {UniValue::VBOOL}); else - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VBOOL)(UniValue::VARR)); + RPCTypeCheck(request.params, {UniValue::VBOOL, UniValue::VARR}); bool fUnlock = request.params[0].get_bool(); @@ -2875,7 +2873,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"") ); - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)); + RPCTypeCheck(request.params, {UniValue::VSTR}); CTxDestination changeAddress = CNoDestination(); int changePosition = -1; @@ -2893,7 +2891,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) includeWatching = request.params[1].get_bool(); } else { - RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ)); + RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ}); UniValue options = request.params[1]; From e9b389d19cd5b42082fcecbf21a968f8707e03d8 Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 5 Jul 2019 00:30:29 -0500 Subject: [PATCH 355/987] continued, dash code Signed-off-by: Pasta --- src/chainparams.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index dc99294368e7..cc0752dec45e 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -537,11 +537,12 @@ class CTestNetParams : public CChainParams { fBIP9CheckMasternodesUpgraded = true; checkpointData = (CCheckpointData) { - boost::assign::map_list_of - ( 261, uint256S("0x00000c26026d0815a7e2ce4fa270775f61403c040647ff2c3091f99e894a4618")) - ( 1999, uint256S("0x00000052e538d27fa53693efe6fb6892a0c1d26c0235f599171c48a3cce553b1")) - ( 2999, uint256S("0x0000024bc3f4f4cb30d29827c13d921ad77d2c6072e586c7f60d83c2722cdcc5")) - ( 96090, uint256S("0x00000000033df4b94d17ab43e999caaf6c4735095cc77703685da81254d09bba")) + { + {261, uint256S("0x00000c26026d0815a7e2ce4fa270775f61403c040647ff2c3091f99e894a4618")}, + {1999, uint256S("0x00000052e538d27fa53693efe6fb6892a0c1d26c0235f599171c48a3cce553b1")}, + {2999, uint256S("0x0000024bc3f4f4cb30d29827c13d921ad77d2c6072e586c7f60d83c2722cdcc5")}, + {96090, uint256S("0x00000000033df4b94d17ab43e999caaf6c4735095cc77703685da81254d09bba")}, + } }; chainTxData = ChainTxData{ @@ -663,9 +664,9 @@ class CDevNetParams : public CChainParams { // Testnet private keys start with '9' or 'c' (Bitcoin defaults) base58Prefixes[SECRET_KEY] = std::vector(1,239); // Testnet Dash BIP32 pubkeys start with 'tpub' (Bitcoin defaults) - base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); + base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; // Testnet Dash BIP32 prvkeys start with 'tprv' (Bitcoin defaults) - base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); + base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; // Testnet Dash BIP44 coin type is '1' (All coin's testnet default) nExtCoinType = 1; From f6400a8713a32954315e65a577ef6eda402af4bd Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 9 Jun 2017 12:58:02 -0700 Subject: [PATCH 356/987] Merge #10521: Limit variable scope 90593ed92 Limit variable scope (practicalswift) Tree-SHA512: 4719e303688a31aefbe1d239e86b21dd3c2045524e08bd628c6ba0c6c2a97de14d04305b9beafe0b1dcde7229793e6663168953f192e88ed409be5c30fd2a9a9 --- src/crypto/aes.cpp | 3 +-- src/qt/coincontroltreewidget.cpp | 5 +++-- src/qt/recentrequeststablemodel.cpp | 3 +-- src/qt/trafficgraphwidget.cpp | 7 ++++--- src/rpc/mining.cpp | 6 ++---- src/test/checkqueue_tests.cpp | 8 ++++---- src/wallet/db.cpp | 2 +- src/wallet/wallet.cpp | 2 +- 8 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp index 1d469d0fb462..5e70d25eeeef 100644 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -112,7 +112,6 @@ static int CBCEncrypt(const T& enc, const unsigned char iv[AES_BLOCKSIZE], const template static int CBCDecrypt(const T& dec, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out) { - unsigned char padsize = 0; int written = 0; bool fail = false; const unsigned char* prev = iv; @@ -136,7 +135,7 @@ static int CBCDecrypt(const T& dec, const unsigned char iv[AES_BLOCKSIZE], const if (pad) { // If used, padding size is the value of the last decrypted byte. For // it to be valid, It must be between 1 and AES_BLOCKSIZE. - padsize = *--out; + unsigned char padsize = *--out; fail = !padsize | (padsize > AES_BLOCKSIZE); // If not well-formed, treat it as though there's no padding. diff --git a/src/qt/coincontroltreewidget.cpp b/src/qt/coincontroltreewidget.cpp index f86bc0851f24..88510b61681d 100644 --- a/src/qt/coincontroltreewidget.cpp +++ b/src/qt/coincontroltreewidget.cpp @@ -16,9 +16,10 @@ void CoinControlTreeWidget::keyPressEvent(QKeyEvent *event) if (event->key() == Qt::Key_Space) // press spacebar -> select checkbox { event->ignore(); - int COLUMN_CHECKBOX = 0; - if(this->currentItem()) + if (this->currentItem()) { + int COLUMN_CHECKBOX = 0; this->currentItem()->setCheckState(COLUMN_CHECKBOX, ((this->currentItem()->checkState(COLUMN_CHECKBOX) == Qt::Checked) ? Qt::Unchecked : Qt::Checked)); + } } else if (event->key() == Qt::Key_Escape) // press esc -> close dialog { diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index 35d37bb22bb0..fd57b494abd6 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -55,10 +55,9 @@ QVariant RecentRequestsTableModel::data(const QModelIndex &index, int role) cons if(!index.isValid() || index.row() >= list.length()) return QVariant(); - const RecentRequestEntry *rec = &list[index.row()]; - if(role == Qt::DisplayRole || role == Qt::EditRole) { + const RecentRequestEntry *rec = &list[index.row()]; switch(index.column()) { case Date: diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 462f745c21ad..8266f553c6dd 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -48,13 +48,14 @@ int TrafficGraphWidget::getGraphRangeMins() const void TrafficGraphWidget::paintPath(QPainterPath &path, const TrafficGraphData::SampleQueue &queue, SampleChooser chooser) { - int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2; - int sampleCount = queue.size(), x = XMARGIN + w, y; + int sampleCount = queue.size(); if(sampleCount > 0) { + int h = height() - YMARGIN * 2, w = width() - XMARGIN * 2; + int x = XMARGIN + w; path.moveTo(x, YMARGIN + h); for(int i = 0; i < sampleCount; ++i) { x = XMARGIN + w - w * i / TrafficGraphData::DESIRED_DATA_SAMPLES; - y = YMARGIN + h - (int)(h * chooser(queue.at(i)) / fMax); + int y = YMARGIN + h - (int)(h * chooser(queue.at(i)) / fMax); path.lineTo(x, y); } path.lineTo(x, YMARGIN + h); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 64c0fdb0672a..00ae7a059350 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -107,15 +107,13 @@ UniValue getnetworkhashps(const JSONRPCRequest& request) UniValue generateBlocks(std::shared_ptr coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) { static const int nInnerLoopCount = 0x10000; - int nHeightStart = 0; int nHeightEnd = 0; int nHeight = 0; { // Don't keep cs_main locked LOCK(cs_main); - nHeightStart = chainActive.Height(); - nHeight = nHeightStart; - nHeightEnd = nHeightStart+nGenerate; + nHeight = chainActive.Height(); + nHeightEnd = nHeight+nGenerate; } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index dee199cd9a80..c0fdefb95a9b 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -402,12 +402,12 @@ BOOST_AUTO_TEST_CASE(test_CheckQueueControl_Locks) { boost::thread_group tg; std::mutex m; - bool has_lock {false}; - bool has_tried {false}; - bool done {false}; - bool done_ack {false}; std::condition_variable cv; { + bool has_lock {false}; + bool has_tried {false}; + bool done {false}; + bool done_ack {false}; std::unique_lock l(m); tg.create_thread([&]{ CCheckQueueControl control(queue.get()); diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 2d4bd21fabea..1935a82e6d80 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -360,7 +360,6 @@ void CDBEnv::CheckpointLSN(const std::string& strFile) CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb(NULL), activeTxn(NULL) { - int ret; fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w')); fFlushOnClose = fFlushOnCloseIn; env = dbw.env; @@ -383,6 +382,7 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb ++env->mapFileUseCount[strFile]; pdb = env->mapDb[strFile]; if (pdb == NULL) { + int ret; pdb = new Db(env->dbenv, 0); bool fMockDb = env->IsMock(); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f95d854e610b..b5712e7ce7ba 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4243,10 +4243,10 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal) bool CWallet::GetKeyFromPool(CPubKey& result, bool fInternal) { - int64_t nIndex = 0; CKeyPool keypool; { LOCK(cs_wallet); + int64_t nIndex = 0; ReserveKeyFromKeyPool(nIndex, keypool, fInternal); if (nIndex == -1) { From 2bfa374729b32283e0c96eed7785e4f466101bf5 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 11 Jun 2017 13:51:46 +0200 Subject: [PATCH 357/987] Merge #10569: Fix stopatheight c45cbaf Fix stopatheight (Andrew Chow) Tree-SHA512: 7df07ca1d40a5a3a8d93ad8943cd04954d587e19bbb63ed084b7aff9503788ec73a1045fbfc4a36d9775975032c2ee0bcc76eb4da10e879f483eaa6f351c19b2 --- src/validation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 9756d96f6cb5..f658d777f905 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2957,6 +2957,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, CBlockIndex *pindexMostWork = NULL; CBlockIndex *pindexNewTip = NULL; + int nStopAtHeight = gArgs.GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); do { boost::this_thread::interruption_point(); if (ShutdownRequested()) @@ -3006,6 +3007,8 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, if (pindexFork != pindexNewTip) { uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip); } + + if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); } while (pindexNewTip != pindexMostWork); CheckBlockIndex(chainparams.GetConsensus()); @@ -3014,9 +3017,6 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams, return false; } - int nStopAtHeight = gArgs.GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); - if (nStopAtHeight && pindexNewTip && pindexNewTip->nHeight >= nStopAtHeight) StartShutdown(); - return true; } From 6a0f565783befd2ec7c0445fb31f0d32f9322f07 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 11 Jun 2017 14:22:00 +0200 Subject: [PATCH 358/987] Merge #10560: Remove unused constants dce8239 Comment out unused constant REJECT_DUST (practicalswift) 3289ef4 Remove unused constant MEMPOOL_GD_VERSION (practicalswift) Tree-SHA512: 8dd772c963037cd0a1db0d5bf5f7a5cce3f5cd8fb6fa983949f9f0c1c8312ffd251a62c1e5d32f3584d2bcc562d8c8a9bf7900609dee9a4f12898caa2be9c38f --- src/consensus/validation.h | 2 +- src/version.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 7c5acb59ff81..2b222f202659 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -14,7 +14,7 @@ static const unsigned char REJECT_INVALID = 0x10; static const unsigned char REJECT_OBSOLETE = 0x11; static const unsigned char REJECT_DUPLICATE = 0x12; static const unsigned char REJECT_NONSTANDARD = 0x40; -static const unsigned char REJECT_DUST = 0x41; +// static const unsigned char REJECT_DUST = 0x41; // part of BIP 61 static const unsigned char REJECT_INSUFFICIENTFEE = 0x42; static const unsigned char REJECT_CHECKPOINT = 0x43; diff --git a/src/version.h b/src/version.h index def3519381ce..dff450406954 100644 --- a/src/version.h +++ b/src/version.h @@ -29,9 +29,6 @@ static const int CADDR_TIME_VERSION = 31402; //! BIP 0031, pong message, is enabled for all versions AFTER this one static const int BIP0031_VERSION = 60000; -//! "mempool" command, enhanced "getdata" behavior starts with this version -static const int MEMPOOL_GD_VERSION = 60002; - //! "filter*" commands are disabled without NODE_BLOOM after and including this version static const int NO_BLOOM_VERSION = 70201; From dc5dc4186b40aa996c0c6449ffc5710e017993f6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 11 Jun 2017 14:23:29 +0200 Subject: [PATCH 359/987] Merge #10566: [docs] Use the "domain name setup" image (previously unused) in the gitian docs 7631066 Use the "domain name setup" image (previously unused) in the gitian docs (practicalswift) Tree-SHA512: 747f3afa15dd6007076fb20d5fd16e20e2fb920c5eea5557664ddd42bd2c52e1a517124a649e3d1605fcc9e0c06a567c63b1023dda22f813a2d331b28097baa0 --- doc/gitian-building.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/gitian-building.md b/doc/gitian-building.md index b121091025cc..0754f95a6407 100644 --- a/doc/gitian-building.md +++ b/doc/gitian-building.md @@ -131,6 +131,7 @@ To select a different button, press `Tab`. - Leave domain name empty. ![](gitian-building/debian_install_5_configure_the_network.png) +![](gitian-building/debian_install_6_domain_name.png) - Choose a root password and enter it twice (remember it for later) From 80b80325017d4821370c4c8d2d25b6e56a7866ec Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 11 Jun 2017 14:31:37 +0200 Subject: [PATCH 360/987] Merge #10561: Remove duplicate includes e53a0fa Remove duplicate includes (practicalswift) Tree-SHA512: 5101afaf190ade3ffbea666ff5d0cb59d3e1dbdd9a3db3d91df7b51c13cc9f5a699438e8a753655365f6dc14529bc95883e715b5a6ab73158374e13ec311f70b --- src/httprpc.cpp | 1 - src/qt/rpcconsole.cpp | 1 - src/wallet/rpcwallet.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 3c4389bdd912..ce64fb444dc9 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -16,7 +16,6 @@ #include "ui_interface.h" #include "crypto/hmac_sha256.h" #include -#include "utilstrencodings.h" #include // boost::trim #include //BOOST_FOREACH diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index b50f11d90a1b..f174c2b04b3e 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -14,7 +14,6 @@ #include "clientmodel.h" #include "guiutil.h" #include "platformstyle.h" - #include "chainparams.h" #include "netbase.h" #include "rpc/server.h" diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 70185800c236..0adbedcf2529 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -10,7 +10,6 @@ #include "consensus/validation.h" #include "core_io.h" #include "init.h" -#include "wallet/coincontrol.h" #include "instantsend.h" #include "net.h" #include "policy/feerate.h" From 1099c1ad608943bdd1c4e9c7746bebecdd20bc9e Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sun, 11 Jun 2017 14:48:51 +0200 Subject: [PATCH 361/987] Merge #10546: Remove 33 unused Boost includes 49de096 Remove unused Boost includes (practicalswift) Tree-SHA512: ff2dad94f9eeb1dc50fcffd0e94e1686be04e4e5bc45f58ae955d630c15cd25bb8f5583d0aa1f2f263b5a723be79747ef3c6e6b417c7be7787c0abc8d1874019 --- src/checkqueue.h | 1 - src/coins.h | 1 + src/dashd.cpp | 1 - src/fs.cpp | 2 -- src/init.cpp | 1 - src/keystore.cpp | 2 -- src/keystore.h | 1 - src/net_processing.cpp | 2 -- src/qt/optionsdialog.cpp | 2 -- src/qt/transactiontablemodel.cpp | 2 -- src/rpc/client.cpp | 1 - src/rpc/server.cpp | 2 -- src/sync.h | 1 - src/test/DoS_tests.cpp | 2 -- src/test/base58_tests.cpp | 1 - src/test/bloom_tests.cpp | 1 - src/test/cuckoocache_tests.cpp | 2 -- src/test/dbwrapper_tests.cpp | 2 -- src/test/sigopcount_tests.cpp | 1 - src/test/streams_tests.cpp | 1 - src/test/test_dash.cpp | 2 -- src/torcontrol.cpp | 1 - src/util.cpp | 1 - src/util.h | 1 - src/validation.cpp | 1 - src/wallet/db.cpp | 1 - src/wallet/test/wallet_tests.cpp | 1 - 27 files changed, 1 insertion(+), 36 deletions(-) diff --git a/src/checkqueue.h b/src/checkqueue.h index 63c104c02a11..08017ff799c8 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -12,7 +12,6 @@ #include #include -#include #include template diff --git a/src/coins.h b/src/coins.h index eef64dc22f70..cb1674abcbbb 100644 --- a/src/coins.h +++ b/src/coins.h @@ -16,6 +16,7 @@ #include #include + #include /** diff --git a/src/dashd.cpp b/src/dashd.cpp index 26cc08cda59d..06e4a0ef9c0a 100644 --- a/src/dashd.cpp +++ b/src/dashd.cpp @@ -22,7 +22,6 @@ #include "utilstrencodings.h" #include "stacktraces.h" -#include #include #include diff --git a/src/fs.cpp b/src/fs.cpp index 6f2b768de322..a5e12f1cfcb7 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -1,7 +1,5 @@ #include "fs.h" -#include - namespace fsbridge { FILE *fopen(const fs::path& p, const char *mode) diff --git a/src/init.cpp b/src/init.cpp index 22f833fc97f4..0712533ac7dc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -85,7 +85,6 @@ #endif #include -#include #include #include #include diff --git a/src/keystore.cpp b/src/keystore.cpp index cc4b1dc4f086..39d685b30a01 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -9,8 +9,6 @@ #include "pubkey.h" #include "util.h" -#include - bool CKeyStore::AddKey(const CKey &key) { return AddKeyPubKey(key, key.GetPubKey()); } diff --git a/src/keystore.h b/src/keystore.h index e81e376cfa1b..9013bfd3cc3d 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -14,7 +14,6 @@ #include "sync.h" #include -#include /** A virtual base class for key stores */ class CKeyStore diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 49083d709cec..5bd7897033cd 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -53,8 +53,6 @@ #include "llmq/quorums_signing.h" #include "llmq/quorums_signing_shares.h" -#include - #if defined(NDEBUG) # error "Dash Core cannot be compiled without assertions." #endif diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 8da87198403e..da3789742064 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -23,8 +23,6 @@ #include "privatesend/privatesend-client.h" #endif // ENABLE_WALLET -#include - #include #include #include diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 36de15b899c2..96fa10bdfb65 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -26,8 +26,6 @@ #include #include -#include - // Amount column is right-aligned it contains numbers static int column_alignments[] = { Qt::AlignLeft|Qt::AlignVCenter, /* status */ diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 5fb3b662c94e..0baf44eaab08 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -11,7 +11,6 @@ #include #include -#include // for to_lower() #include class CRPCConvertParam diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index eefde0e5e962..8eb15d315319 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -19,9 +19,7 @@ #include #include -#include #include -#include #include // for to_upper() #include #include diff --git a/src/sync.h b/src/sync.h index ea34f1c4e2b1..75e8b3acce06 100644 --- a/src/sync.h +++ b/src/sync.h @@ -9,7 +9,6 @@ #include "threadsafety.h" #include -#include #include #include diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp index 9ce9688ebb41..2b251a8b1a9a 100644 --- a/src/test/DoS_tests.cpp +++ b/src/test/DoS_tests.cpp @@ -18,8 +18,6 @@ #include -#include -#include #include // Tests these internal-to-net_processing.cpp methods: diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 2d26bbfe1e64..fba69759ce73 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -15,7 +15,6 @@ #include "utilstrencodings.h" #include "test/test_dash.h" -#include #include #include diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index 21ea5c25b06b..8f14db900158 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -19,7 +19,6 @@ #include #include -#include BOOST_FIXTURE_TEST_SUITE(bloom_tests, BasicTestingSetup) diff --git a/src/test/cuckoocache_tests.cpp b/src/test/cuckoocache_tests.cpp index 7c6abc4d707e..be46d293b922 100644 --- a/src/test/cuckoocache_tests.cpp +++ b/src/test/cuckoocache_tests.cpp @@ -7,8 +7,6 @@ #include "test/test_dash.h" #include "random.h" #include -#include - /** Test Suite for CuckooCache * diff --git a/src/test/dbwrapper_tests.cpp b/src/test/dbwrapper_tests.cpp index 571e06f312c3..156c19315c65 100644 --- a/src/test/dbwrapper_tests.cpp +++ b/src/test/dbwrapper_tests.cpp @@ -7,8 +7,6 @@ #include "random.h" #include "test/test_dash.h" -#include // for 'operator+=()' -#include #include // Test if a string consists entirely of null characters diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp index ae79bec4be81..8bea5496e974 100644 --- a/src/test/sigopcount_tests.cpp +++ b/src/test/sigopcount_tests.cpp @@ -11,7 +11,6 @@ #include -#include #include // Helpers: diff --git a/src/test/streams_tests.cpp b/src/test/streams_tests.cpp index 186961aa3aae..b1bcb4301c02 100644 --- a/src/test/streams_tests.cpp +++ b/src/test/streams_tests.cpp @@ -7,7 +7,6 @@ #include "test/test_dash.h" #include // for 'operator+=()' -#include #include using namespace boost::assign; // bring 'operator+=()' into scope diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index 72060363d2ec..a99b6ac498fb 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -30,8 +30,6 @@ #include -#include - uint256 insecure_rand_seed = GetRandHash(); FastRandomContext insecure_rand_ctx(insecure_rand_seed); diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 86d839558cb7..e2ba2209b1df 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/src/util.cpp b/src/util.cpp index 5001af45c6b2..581b1faf48d2 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -85,7 +85,6 @@ #include // for startswith() and endswith() #include #include -#include #include #include #include diff --git a/src/util.h b/src/util.h index 2e4b4a693f8f..a38c010efbc9 100644 --- a/src/util.h +++ b/src/util.h @@ -31,7 +31,6 @@ #include #include -#include // Debugging macros diff --git a/src/validation.cpp b/src/validation.cpp index f658d777f905..5541eb645253 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -56,7 +56,6 @@ #include #include -#include #include #if defined(NDEBUG) diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 1935a82e6d80..67f9f223f01d 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -20,7 +20,6 @@ #include #include -#include // // CDB diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 31ea7a59d5ed..76e322c9cf46 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -14,7 +14,6 @@ #include "validation.h" #include "wallet/test/wallet_test_fixture.h" -#include #include #include From d93b837326f27a509766651546c9cd4701d928f0 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 8 Jul 2019 13:38:47 -0500 Subject: [PATCH 362/987] Use InsecureRandRange instead of InsecureRandBool Signed-off-by: Pasta --- src/test/sighash_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index d6f6342a657d..c75bec383265 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -93,7 +93,7 @@ void static RandomScript(CScript &script) { } void static RandomTransaction(CMutableTransaction &tx, bool fSingle) { - tx.nVersion = (InsecureRandBool()) + 1; + tx.nVersion = InsecureRandRange(2) + 1; tx.vin.clear(); tx.vout.clear(); tx.nLockTime = (InsecureRandBool()) ? InsecureRand32() : 0; From 594eb7444205d1ed8f1dadb184791e2212068662 Mon Sep 17 00:00:00 2001 From: Pasta Date: Mon, 8 Jul 2019 13:39:58 -0500 Subject: [PATCH 363/987] remove unneeded parenthesises Signed-off-by: Pasta --- src/test/coins_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 09771e241ba2..f6e8adab802c 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -145,8 +145,8 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) // Determine whether to test HaveCoin before or after Access* (or both). As these functions // can influence each other's behaviour by pulling things into the cache, all combinations // are tested. - bool test_havecoin_before = (InsecureRandBits(2)) == 0; - bool test_havecoin_after = (InsecureRandBits(2)) == 0; + bool test_havecoin_before = InsecureRandBits(2) == 0; + bool test_havecoin_after = InsecureRandBits(2) == 0; bool result_havecoin = test_havecoin_before ? stack.back()->HaveCoin(COutPoint(txid, 0)) : false; const Coin& entry = (InsecureRandRange(500) == 0) ? AccessByTxid(*stack.back(), txid) : stack.back()->AccessCoin(COutPoint(txid, 0)); From 7a440d626b312c7c7e2701379cf7c124c8f8fe0f Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 9 Jul 2019 07:59:57 +0200 Subject: [PATCH 364/987] Optimize on-disk deterministic masternode storage to reduce size of evodb (#3017) * Implement CompactFull() in CDBWrapper This allows to compact the whole DB in one go. * Implement more compact version of CDeterministicMNListDiff This introduces CDeterministicMNStateDiff which requires to only store fields on-disk which actually changed. * Avoid writing mnUniquePropertyMap to disk when storing snapshots This map can be rebuilt by simply using AddMN for each deserialized MN. * Implement Serialize/Unserialize in CScript This allows us to directly use READWRITE() on scripts and removes the need for the ugly cast to CScriptBase. This commit also changes all Dash specific uses of CScript to not use the cast. * Keep track of registeration counts and introduce internalID for masternodes The "internalId" is simply the number of MNs registered so far when the new MN is added. It is deterministic and stays the same forever. * Use internalId as keys in MN list diffs This reduces the used size on-disk. * Two simple speedups in MN list diff handling 1. Avoid full compare if dmn or state pointers match in BuildDiff 2. Use std::move when adding diff to listDiff in GetListForBlock * Implement upgrade code for old CDeterministicMNListDiff format to new format * Track tipIndex instead of tipHeight/tipBlockHash * Store and pass around CBlockIndex* instead of block hash and height This allows us to switch CDeterministicMNManager::GetListForBlock to work with CBlockIndex. * Refactor CDeterministicMNManager::GetListForBlock to require CBlockIndex* Instead of requiring a block hash. This allows us to remove blockHash and prevBlockHash from CDeterministicMNListDiff without the use of cs_main locks in GetListForBlock. * Remove prevBlockHash, blockHash and nHeight from CDeterministicMNListDiff * Remove access to determinisitcMNManager in CMasternodeMetaMan::ToString() The deterministic MN manager is not fully initialized yet at the time this is called, which results in an empty list being returned everytime. * Better logic to determine if an upgrade is needed Reuse the "best block" logic to figure out if an upgrade is needed. Also use it to ensure that older nodes are unable to start after the upgrade was performed. * Return null block hash if it was requested with getmnlistdiff * bump CGovernanceManager::SERIALIZATION_VERSION_STRING * Check SERIALIZATION_VERSION_STRING before deserializing anything else * Invoke Clear() before deserializing just to be sure --- src/dbwrapper.h | 5 + src/evo/deterministicmns.cpp | 265 ++++++++++++++++++++----- src/evo/deterministicmns.h | 264 +++++++++++++++++++----- src/evo/evodb.h | 4 +- src/evo/mnauth.cpp | 10 +- src/evo/providertx.cpp | 8 +- src/evo/providertx.h | 6 +- src/evo/simplifiedmns.cpp | 9 +- src/governance/governance.cpp | 12 +- src/governance/governance.h | 8 +- src/init.cpp | 2 + src/llmq/quorums.cpp | 14 +- src/llmq/quorums.h | 4 +- src/llmq/quorums_blockprocessor.cpp | 9 +- src/llmq/quorums_commitment.cpp | 2 +- src/llmq/quorums_debug.cpp | 13 +- src/llmq/quorums_dkgsession.cpp | 35 ++-- src/llmq/quorums_dkgsession.h | 5 +- src/llmq/quorums_dkgsessionhandler.cpp | 22 +- src/llmq/quorums_dkgsessionhandler.h | 2 +- src/llmq/quorums_dkgsessionmgr.cpp | 22 +- src/llmq/quorums_dkgsessionmgr.h | 8 +- src/llmq/quorums_utils.cpp | 14 +- src/llmq/quorums_utils.h | 6 +- src/masternode/activemasternode.cpp | 2 +- src/masternode/masternode-meta.cpp | 1 - src/masternode/masternode-meta.h | 8 +- src/masternode/masternode-payments.cpp | 8 +- src/rpc/rpcevo.cpp | 4 +- src/rpc/rpcquorums.cpp | 4 +- src/script/script.h | 9 + src/spentindex.h | 2 +- 32 files changed, 569 insertions(+), 218 deletions(-) diff --git a/src/dbwrapper.h b/src/dbwrapper.h index a20998f7fe71..fb831e5582a6 100644 --- a/src/dbwrapper.h +++ b/src/dbwrapper.h @@ -390,6 +390,11 @@ class CDBWrapper pdb->CompactRange(&slKey1, &slKey2); } + void CompactFull() const + { + pdb->CompactRange(nullptr, nullptr); + } + }; template diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 96bb8086a82e..921905e1aaff 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -182,6 +182,15 @@ CDeterministicMNCPtr CDeterministicMNList::GetValidMNByService(const CService& s return dmn; } +CDeterministicMNCPtr CDeterministicMNList::GetMNByInternalId(uint64_t internalId) const +{ + auto proTxHash = mnInternalIdMap.find(internalId); + if (!proTxHash) { + return nullptr; + } + return GetMN(*proTxHash); +} + static int CompareByLastPaid_GetHeight(const CDeterministicMN& dmn) { int height = dmn.pdmnState->nLastPaidHeight; @@ -349,25 +358,31 @@ void CDeterministicMNList::PoSeDecrease(const uint256& proTxHash) CDeterministicMNListDiff CDeterministicMNList::BuildDiff(const CDeterministicMNList& to) const { CDeterministicMNListDiff diffRet; - diffRet.prevBlockHash = blockHash; - diffRet.blockHash = to.blockHash; - diffRet.nHeight = to.nHeight; to.ForEachMN(false, [&](const CDeterministicMNCPtr& toPtr) { auto fromPtr = GetMN(toPtr->proTxHash); if (fromPtr == nullptr) { - diffRet.addedMNs.emplace(toPtr->proTxHash, toPtr); - } else if (*toPtr->pdmnState != *fromPtr->pdmnState) { - diffRet.updatedMNs.emplace(toPtr->proTxHash, toPtr->pdmnState); + diffRet.addedMNs.emplace_back(toPtr); + } else if (fromPtr != toPtr || fromPtr->pdmnState != toPtr->pdmnState) { + CDeterministicMNStateDiff stateDiff(*fromPtr->pdmnState, *toPtr->pdmnState); + if (stateDiff.fields) { + diffRet.updatedMNs.emplace(toPtr->internalId, std::move(stateDiff)); + } } }); ForEachMN(false, [&](const CDeterministicMNCPtr& fromPtr) { auto toPtr = to.GetMN(fromPtr->proTxHash); if (toPtr == nullptr) { - diffRet.removedMns.insert(fromPtr->proTxHash); + diffRet.removedMns.emplace(fromPtr->internalId); } }); + // added MNs need to be sorted by internalId so that these are added in correct order when the diff is applied later + // otherwise internalIds will not match with the original list + std::sort(diffRet.addedMNs.begin(), diffRet.addedMNs.end(), [](const CDeterministicMNCPtr& a, const CDeterministicMNCPtr& b) { + return a->internalId < b->internalId; + }); + return diffRet; } @@ -399,22 +414,25 @@ CSimplifiedMNListDiff CDeterministicMNList::BuildSimplifiedDiff(const CDetermini return diffRet; } -CDeterministicMNList CDeterministicMNList::ApplyDiff(const CDeterministicMNListDiff& diff) const +CDeterministicMNList CDeterministicMNList::ApplyDiff(const CBlockIndex* pindex, const CDeterministicMNListDiff& diff) const { - assert(diff.prevBlockHash == blockHash && diff.nHeight == nHeight + 1); - CDeterministicMNList result = *this; - result.blockHash = diff.blockHash; - result.nHeight = diff.nHeight; + result.blockHash = pindex->GetBlockHash(); + result.nHeight = pindex->nHeight; - for (const auto& hash : diff.removedMns) { - result.RemoveMN(hash); + for (const auto& id : diff.removedMns) { + auto dmn = result.GetMNByInternalId(id); + assert(dmn); + result.RemoveMN(dmn->proTxHash); } - for (const auto& p : diff.addedMNs) { - result.AddMN(p.second); + for (const auto& dmn : diff.addedMNs) { + assert(dmn->internalId == result.GetTotalRegisteredCount()); + result.AddMN(dmn); + result.SetTotalRegisteredCount(result.GetTotalRegisteredCount() + 1); } for (const auto& p : diff.updatedMNs) { - result.UpdateMN(p.first, p.second); + auto dmn = result.GetMNByInternalId(p.first); + result.UpdateMN(dmn, p.second); } return result; @@ -424,6 +442,7 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn) { assert(!mnMap.find(dmn->proTxHash)); mnMap = mnMap.set(dmn->proTxHash, dmn); + mnInternalIdMap = mnInternalIdMap.set(dmn->internalId, dmn->proTxHash); AddUniqueProperty(dmn, dmn->collateralOutpoint); if (dmn->pdmnState->addr != CService()) { AddUniqueProperty(dmn, dmn->pdmnState->addr); @@ -434,20 +453,35 @@ void CDeterministicMNList::AddMN(const CDeterministicMNCPtr& dmn) } } -void CDeterministicMNList::UpdateMN(const uint256& proTxHash, const CDeterministicMNStateCPtr& pdmnState) +void CDeterministicMNList::UpdateMN(const CDeterministicMNCPtr& oldDmn, const CDeterministicMNStateCPtr& pdmnState) { - auto oldDmn = mnMap.find(proTxHash); assert(oldDmn != nullptr); - auto dmn = std::make_shared(**oldDmn); + auto dmn = std::make_shared(*oldDmn); auto oldState = dmn->pdmnState; dmn->pdmnState = pdmnState; - mnMap = mnMap.set(proTxHash, dmn); + mnMap = mnMap.set(oldDmn->proTxHash, dmn); UpdateUniqueProperty(dmn, oldState->addr, pdmnState->addr); UpdateUniqueProperty(dmn, oldState->keyIDOwner, pdmnState->keyIDOwner); UpdateUniqueProperty(dmn, oldState->pubKeyOperator, pdmnState->pubKeyOperator); } +void CDeterministicMNList::UpdateMN(const uint256& proTxHash, const CDeterministicMNStateCPtr& pdmnState) +{ + auto oldDmn = mnMap.find(proTxHash); + assert(oldDmn != nullptr); + UpdateMN(*oldDmn, pdmnState); +} + +void CDeterministicMNList::UpdateMN(const CDeterministicMNCPtr& oldDmn, const CDeterministicMNStateDiff& stateDiff) +{ + assert(oldDmn != nullptr); + auto oldState = oldDmn->pdmnState; + auto newState = std::make_shared(*oldState); + stateDiff.ApplyToState(*newState); + UpdateMN(oldDmn, newState); +} + void CDeterministicMNList::RemoveMN(const uint256& proTxHash) { auto dmn = GetMN(proTxHash); @@ -461,6 +495,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash) DeleteUniqueProperty(dmn, dmn->pdmnState->pubKeyOperator); } mnMap = mnMap.erase(proTxHash); + mnInternalIdMap = mnInternalIdMap.erase(dmn->internalId); } CDeterministicMNManager::CDeterministicMNManager(CEvoDB& _evoDb) : @@ -500,12 +535,12 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde newList.SetBlockHash(block.GetHash()); - oldList = GetListForBlock(pindex->pprev->GetBlockHash()); + oldList = GetListForBlock(pindex->pprev); diff = oldList.BuildDiff(newList); - evoDb.Write(std::make_pair(DB_LIST_DIFF, diff.blockHash), diff); + evoDb.Write(std::make_pair(DB_LIST_DIFF, newList.GetBlockHash()), diff); if ((nHeight % SNAPSHOT_LIST_PERIOD) == 0 || oldList.GetHeight() == -1) { - evoDb.Write(std::make_pair(DB_LIST_SNAPSHOT, diff.blockHash), newList); + evoDb.Write(std::make_pair(DB_LIST_SNAPSHOT, newList.GetBlockHash()), newList); LogPrintf("CDeterministicMNManager::%s -- Wrote snapshot. nHeight=%d, mapCurMNs.allMNsCount=%d\n", __func__, nHeight, newList.GetAllMNsCount()); } @@ -546,8 +581,8 @@ bool CDeterministicMNManager::UndoBlock(const CBlock& block, const CBlockIndex* if (diff.HasChanges()) { // need to call this before erasing - curList = GetListForBlock(blockHash); - prevList = GetListForBlock(pindex->pprev->GetBlockHash()); + curList = GetListForBlock(pindex); + prevList = GetListForBlock(pindex->pprev); } evoDb.Erase(std::make_pair(DB_LIST_DIFF, blockHash)); @@ -574,8 +609,7 @@ void CDeterministicMNManager::UpdatedBlockTip(const CBlockIndex* pindex) { LOCK(cs); - tipHeight = pindex->nHeight; - tipBlockHash = pindex->GetBlockHash(); + tipIndex = pindex; } bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, CValidationState& _state, CDeterministicMNList& mnListRet, bool debugLogs) @@ -584,7 +618,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C int nHeight = pindexPrev->nHeight + 1; - CDeterministicMNList oldList = GetListForBlock(pindexPrev->GetBlockHash()); + CDeterministicMNList oldList = GetListForBlock(pindexPrev); CDeterministicMNList newList = oldList; newList.SetBlockHash(uint256()); // we can't know the final block hash, so better not return a (invalid) block hash newList.SetHeight(nHeight); @@ -628,6 +662,8 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C auto dmn = std::make_shared(); dmn->proTxHash = tx.GetHash(); + dmn->internalId = newList.GetTotalRegisteredCount(); + newList.SetTotalRegisteredCount(newList.GetTotalRegisteredCount() + 1); // collateralOutpoint is either pointing to an external collateral or to the ProRegTx itself if (proTx.collateralOutpoint.hash.IsNull()) { @@ -771,7 +807,15 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C assert(false); // this should have been handled already } if (!qc.commitment.IsNull()) { - HandleQuorumCommitment(qc.commitment, newList, debugLogs); + const auto& params = Params().GetConsensus().llmqs.at(qc.commitment.llmqType); + int quorumHeight = qc.nHeight - (qc.nHeight % params.dkgInterval); + auto quorumIndex = pindexPrev->GetAncestor(quorumHeight); + if (!quorumIndex || quorumIndex->GetBlockHash() != qc.commitment.quorumHash) { + // we should actually never get into this case as validation should have catched it...but lets be sure + return _state.DoS(100, false, REJECT_INVALID, "bad-qc-quorum-hash"); + } + + HandleQuorumCommitment(qc.commitment, quorumIndex, newList, debugLogs); } } } @@ -807,11 +851,11 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C return true; } -void CDeterministicMNManager::HandleQuorumCommitment(llmq::CFinalCommitment& qc, CDeterministicMNList& mnList, bool debugLogs) +void CDeterministicMNManager::HandleQuorumCommitment(llmq::CFinalCommitment& qc, const CBlockIndex* pindexQuorum, CDeterministicMNList& mnList, bool debugLogs) { // The commitment has already been validated at this point so it's safe to use members of it - auto members = llmq::CLLMQUtils::GetAllQuorumMembers((Consensus::LLMQType)qc.llmqType, qc.quorumHash); + auto members = llmq::CLLMQUtils::GetAllQuorumMembers((Consensus::LLMQType)qc.llmqType, pindexQuorum); for (size_t i = 0; i < members.size(); i++) { if (!mnList.HasMN(members[i]->proTxHash)) { @@ -844,52 +888,48 @@ void CDeterministicMNManager::DecreasePoSePenalties(CDeterministicMNList& mnList } } -CDeterministicMNList CDeterministicMNManager::GetListForBlock(const uint256& blockHash) +CDeterministicMNList CDeterministicMNManager::GetListForBlock(const CBlockIndex* pindex) { LOCK(cs); - auto it = mnListsCache.find(blockHash); - if (it != mnListsCache.end()) { - return it->second; - } - - uint256 blockHashTmp = blockHash; CDeterministicMNList snapshot; - std::list listDiff; + std::list> listDiff; while (true) { // try using cache before reading from disk - it = mnListsCache.find(blockHashTmp); + auto it = mnListsCache.find(pindex->GetBlockHash()); if (it != mnListsCache.end()) { snapshot = it->second; break; } - if (evoDb.Read(std::make_pair(DB_LIST_SNAPSHOT, blockHashTmp), snapshot)) { - mnListsCache.emplace(blockHashTmp, snapshot); + if (evoDb.Read(std::make_pair(DB_LIST_SNAPSHOT, pindex->GetBlockHash()), snapshot)) { + mnListsCache.emplace(pindex->GetBlockHash(), snapshot); break; } CDeterministicMNListDiff diff; - if (!evoDb.Read(std::make_pair(DB_LIST_DIFF, blockHashTmp), diff)) { - snapshot = CDeterministicMNList(blockHashTmp, -1); - mnListsCache.emplace(blockHashTmp, snapshot); + if (!evoDb.Read(std::make_pair(DB_LIST_DIFF, pindex->GetBlockHash()), diff)) { + snapshot = CDeterministicMNList(pindex->GetBlockHash(), -1, 0); + mnListsCache.emplace(pindex->GetBlockHash(), snapshot); break; } - listDiff.emplace_front(diff); - blockHashTmp = diff.prevBlockHash; + listDiff.emplace_front(pindex, std::move(diff)); + pindex = pindex->pprev; } - for (const auto& diff : listDiff) { + for (const auto& p : listDiff) { + auto diffIndex = p.first; + auto& diff = p.second; if (diff.HasChanges()) { - snapshot = snapshot.ApplyDiff(diff); + snapshot = snapshot.ApplyDiff(diffIndex, diff); } else { - snapshot.SetBlockHash(diff.blockHash); - snapshot.SetHeight(diff.nHeight); + snapshot.SetBlockHash(diffIndex->GetBlockHash()); + snapshot.SetHeight(diffIndex->nHeight); } - mnListsCache.emplace(diff.blockHash, snapshot); + mnListsCache.emplace(diffIndex->GetBlockHash(), snapshot); } return snapshot; @@ -898,7 +938,10 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlock(const uint256& blo CDeterministicMNList CDeterministicMNManager::GetListAtChainTip() { LOCK(cs); - return GetListForBlock(tipBlockHash); + if (!tipIndex) { + return {}; + } + return GetListForBlock(tipIndex); } bool CDeterministicMNManager::IsProTxWithCollateral(const CTransactionRef& tx, uint32_t n) @@ -928,7 +971,7 @@ bool CDeterministicMNManager::IsDIP3Enforced(int nHeight) LOCK(cs); if (nHeight == -1) { - nHeight = tipHeight; + nHeight = tipIndex->nHeight; } return nHeight >= Params().GetConsensus().DIP0003EnforcementHeight; @@ -948,3 +991,115 @@ void CDeterministicMNManager::CleanupCache(int nHeight) mnListsCache.erase(h); } } + +bool CDeterministicMNManager::UpgradeDiff(CDBBatch& batch, const CBlockIndex* pindexNext, const CDeterministicMNList& curMNList, CDeterministicMNList& newMNList) +{ + CDataStream oldDiffData(SER_DISK, CLIENT_VERSION); + if (!evoDb.GetRawDB().ReadDataStream(std::make_pair(DB_LIST_DIFF, pindexNext->GetBlockHash()), oldDiffData)) { + LogPrintf("CDeterministicMNManager::%s -- no diff found for %s\n", __func__, pindexNext->GetBlockHash().ToString()); + newMNList = curMNList; + newMNList.SetBlockHash(pindexNext->GetBlockHash()); + newMNList.SetHeight(pindexNext->nHeight); + return false; + } + + CDeterministicMNListDiff_OldFormat oldDiff; + oldDiffData >> oldDiff; + + CDeterministicMNListDiff newDiff; + size_t addedCount = 0; + for (auto& p : oldDiff.addedMNs) { + auto dmn = std::make_shared(*p.second); + dmn->internalId = curMNList.GetTotalRegisteredCount() + addedCount; + newDiff.addedMNs.emplace_back(dmn); + + addedCount++; + } + for (auto& p : oldDiff.removedMns) { + auto dmn = curMNList.GetMN(p); + newDiff.removedMns.emplace(dmn->internalId); + } + + // applies added/removed MNs + newMNList = curMNList.ApplyDiff(pindexNext, newDiff); + + // manually apply updated MNs and calc new state diffs + for (auto& p : oldDiff.updatedMNs) { + auto oldMN = newMNList.GetMN(p.first); + newMNList.UpdateMN(p.first, p.second); + auto newMN = newMNList.GetMN(p.first); + assert(oldMN && newMN); + + newDiff.updatedMNs.emplace(std::piecewise_construct, + std::forward_as_tuple(oldMN->internalId), + std::forward_as_tuple(*oldMN->pdmnState, *newMN->pdmnState)); + } + + batch.Write(std::make_pair(DB_LIST_DIFF, pindexNext->GetBlockHash()), newDiff); + + return true; +} + +// TODO this can be completely removed in a future version +void CDeterministicMNManager::UpgradeDBIfNeeded() +{ + LOCK(cs_main); + + if (chainActive.Tip() == nullptr) { + return; + } + + if (evoDb.GetRawDB().Exists(EVODB_BEST_BLOCK)) { + return; + } + + // Removing the old EVODB_BEST_BLOCK value early results in older version to crash immediately, even if the upgrade + // process is cancelled in-between. But if the new version sees that the old EVODB_BEST_BLOCK is already removed, + // then we must assume that the upgrade process was already running before but was interrupted. + if (chainActive.Height() > 1 && !evoDb.GetRawDB().Exists(std::string("b_b"))) { + LogPrintf("CDeterministicMNManager::%s -- ERROR, upgrade process was interrupted and can't be continued. You need to reindex now.\n", __func__); + } + evoDb.GetRawDB().Erase(std::string("b_b")); + + if (chainActive.Height() < Params().GetConsensus().DIP0003Height) { + // not reached DIP3 height yet, so no upgrade needed + auto dbTx = evoDb.BeginTransaction(); + evoDb.WriteBestBlock(chainActive.Tip()->GetBlockHash()); + dbTx->Commit(); + return; + } + + LogPrintf("CDeterministicMNManager::%s -- upgrading DB to use compact diffs\n", __func__); + + CDBBatch batch(evoDb.GetRawDB()); + + CDeterministicMNList curMNList; + curMNList.SetHeight(Params().GetConsensus().DIP0003Height - 1); + curMNList.SetBlockHash(chainActive[Params().GetConsensus().DIP0003Height - 1]->GetBlockHash()); + + for (int nHeight = Params().GetConsensus().DIP0003Height; nHeight <= chainActive.Height(); nHeight++) { + auto pindex = chainActive[nHeight]; + + CDeterministicMNList newMNList; + UpgradeDiff(batch, pindex, curMNList, newMNList); + + if ((nHeight % SNAPSHOT_LIST_PERIOD) == 0) { + batch.Write(std::make_pair(DB_LIST_SNAPSHOT, pindex->GetBlockHash()), newMNList); + evoDb.GetRawDB().WriteBatch(batch); + batch.Clear(); + } + + curMNList = newMNList; + } + + evoDb.GetRawDB().WriteBatch(batch); + + LogPrintf("CDeterministicMNManager::%s -- done upgrading\n", __func__); + + // Writing EVODB_BEST_BLOCK (which is b_b2 now) marks the DB as upgraded + auto dbTx = evoDb.BeginTransaction(); + evoDb.WriteBestBlock(chainActive.Tip()->GetBlockHash()); + dbTx->Commit(); + + evoDb.GetRawDB().CompactFull(); +} diff --git a/src/evo/deterministicmns.h b/src/evo/deterministicmns.h index a917e95b34e3..d8702c518660 100644 --- a/src/evo/deterministicmns.h +++ b/src/evo/deterministicmns.h @@ -83,8 +83,8 @@ class CDeterministicMNState READWRITE(pubKeyOperator); READWRITE(keyIDVoting); READWRITE(addr); - READWRITE(*(CScriptBase*)(&scriptPayout)); - READWRITE(*(CScriptBase*)(&scriptOperatorPayout)); + READWRITE(scriptPayout); + READWRITE(scriptOperatorPayout); } void ResetOperatorFields() @@ -109,35 +109,81 @@ class CDeterministicMNState h.Finalize(confirmedHashWithProRegTxHash.begin()); } - bool operator==(const CDeterministicMNState& rhs) const +public: + std::string ToString() const; + void ToJson(UniValue& obj) const; +}; +typedef std::shared_ptr CDeterministicMNStatePtr; +typedef std::shared_ptr CDeterministicMNStateCPtr; + +class CDeterministicMNStateDiff +{ +public: + enum Field : uint32_t { + Field_nRegisteredHeight = 0x0001, + Field_nLastPaidHeight = 0x0002, + Field_nPoSePenalty = 0x0004, + Field_nPoSeRevivedHeight = 0x0008, + Field_nPoSeBanHeight = 0x0010, + Field_nRevocationReason = 0x0020, + Field_confirmedHash = 0x0040, + Field_confirmedHashWithProRegTxHash = 0x0080, + Field_keyIDOwner = 0x0100, + Field_pubKeyOperator = 0x0200, + Field_keyIDVoting = 0x0400, + Field_addr = 0x0800, + Field_scriptPayout = 0x1000, + Field_scriptOperatorPayout = 0x2000, + }; + +#define DMN_STATE_DIFF_ALL_FIELDS \ + DMN_STATE_DIFF_LINE(nRegisteredHeight) \ + DMN_STATE_DIFF_LINE(nLastPaidHeight) \ + DMN_STATE_DIFF_LINE(nPoSePenalty) \ + DMN_STATE_DIFF_LINE(nPoSeRevivedHeight) \ + DMN_STATE_DIFF_LINE(nPoSeBanHeight) \ + DMN_STATE_DIFF_LINE(nRevocationReason) \ + DMN_STATE_DIFF_LINE(confirmedHash) \ + DMN_STATE_DIFF_LINE(confirmedHashWithProRegTxHash) \ + DMN_STATE_DIFF_LINE(keyIDOwner) \ + DMN_STATE_DIFF_LINE(pubKeyOperator) \ + DMN_STATE_DIFF_LINE(keyIDVoting) \ + DMN_STATE_DIFF_LINE(addr) \ + DMN_STATE_DIFF_LINE(scriptPayout) \ + DMN_STATE_DIFF_LINE(scriptOperatorPayout) + +public: + uint32_t fields{0}; + // we reuse the state class, but only the members as noted by fields are valid + CDeterministicMNState state; + +public: + CDeterministicMNStateDiff() {} + CDeterministicMNStateDiff(const CDeterministicMNState& a, const CDeterministicMNState& b) { - return nRegisteredHeight == rhs.nRegisteredHeight && - nLastPaidHeight == rhs.nLastPaidHeight && - nPoSePenalty == rhs.nPoSePenalty && - nPoSeRevivedHeight == rhs.nPoSeRevivedHeight && - nPoSeBanHeight == rhs.nPoSeBanHeight && - nRevocationReason == rhs.nRevocationReason && - confirmedHash == rhs.confirmedHash && - confirmedHashWithProRegTxHash == rhs.confirmedHashWithProRegTxHash && - keyIDOwner == rhs.keyIDOwner && - pubKeyOperator == rhs.pubKeyOperator && - keyIDVoting == rhs.keyIDVoting && - addr == rhs.addr && - scriptPayout == rhs.scriptPayout && - scriptOperatorPayout == rhs.scriptOperatorPayout; +#define DMN_STATE_DIFF_LINE(f) if (a.f != b.f) { state.f = b.f; fields |= Field_##f; } + DMN_STATE_DIFF_ALL_FIELDS +#undef DMN_STATE_DIFF_LINE } - bool operator!=(const CDeterministicMNState& rhs) const + ADD_SERIALIZE_METHODS; + + template + inline void SerializationOp(Stream& s, Operation ser_action) { - return !(rhs == *this); + READWRITE(VARINT(fields)); +#define DMN_STATE_DIFF_LINE(f) if (fields & Field_##f) READWRITE(state.f); + DMN_STATE_DIFF_ALL_FIELDS +#undef DMN_STATE_DIFF_LINE } -public: - std::string ToString() const; - void ToJson(UniValue& obj) const; + void ApplyToState(CDeterministicMNState& target) const + { +#define DMN_STATE_DIFF_LINE(f) if (fields & Field_##f) target.f = state.f; + DMN_STATE_DIFF_ALL_FIELDS +#undef DMN_STATE_DIFF_LINE + } }; -typedef std::shared_ptr CDeterministicMNStatePtr; -typedef std::shared_ptr CDeterministicMNStateCPtr; class CDeterministicMN { @@ -150,22 +196,36 @@ class CDeterministicMN } uint256 proTxHash; + uint64_t internalId{std::numeric_limits::max()}; COutPoint collateralOutpoint; uint16_t nOperatorReward; CDeterministicMNStateCPtr pdmnState; public: - ADD_SERIALIZE_METHODS; - template - inline void SerializationOp(Stream& s, Operation ser_action) + inline void SerializationOp(Stream& s, Operation ser_action, bool oldFormat) { READWRITE(proTxHash); + if (!oldFormat) { + READWRITE(VARINT(internalId)); + } READWRITE(collateralOutpoint); READWRITE(nOperatorReward); READWRITE(pdmnState); } + template + void Serialize(Stream& s) const + { + NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize(), false); + } + + template + void Unserialize(Stream& s, bool oldFormat = false) + { + SerializationOp(s, CSerActionUnserialize(), oldFormat); + } + public: std::string ToString() const; void ToJson(UniValue& obj) const; @@ -214,35 +274,60 @@ class CDeterministicMNList { public: typedef immer::map MnMap; + typedef immer::map MnInternalIdMap; typedef immer::map > MnUniquePropertyMap; private: uint256 blockHash; int nHeight{-1}; + uint32_t nTotalRegisteredCount{0}; MnMap mnMap; + MnInternalIdMap mnInternalIdMap; // map of unique properties like address and keys // we keep track of this as checking for duplicates would otherwise be painfully slow - // the entries in the map are ref counted as some properties might appear multiple times per MN (e.g. operator/owner keys) MnUniquePropertyMap mnUniquePropertyMap; public: CDeterministicMNList() {} - explicit CDeterministicMNList(const uint256& _blockHash, int _height) : + explicit CDeterministicMNList(const uint256& _blockHash, int _height, uint32_t _totalRegisteredCount) : blockHash(_blockHash), - nHeight(_height) + nHeight(_height), + nTotalRegisteredCount(_totalRegisteredCount) { } - ADD_SERIALIZE_METHODS; - template - inline void SerializationOp(Stream& s, Operation ser_action) + inline void SerializationOpBase(Stream& s, Operation ser_action) { READWRITE(blockHash); READWRITE(nHeight); - READWRITE(mnMap); - READWRITE(mnUniquePropertyMap); + READWRITE(nTotalRegisteredCount); + } + + template + void Serialize(Stream& s) const + { + NCONST_PTR(this)->SerializationOpBase(s, CSerActionSerialize()); + // Serialize the map as a vector + WriteCompactSize(s, mnMap.size()); + for (const auto& p : mnMap) { + s << *p.second; + } + } + + template + void Unserialize(Stream& s) { + mnMap = MnMap(); + mnUniquePropertyMap = MnUniquePropertyMap(); + mnInternalIdMap = MnInternalIdMap(); + + SerializationOpBase(s, CSerActionUnserialize()); + + size_t cnt = ReadCompactSize(s); + for (size_t i = 0; i < cnt; i++) { + AddMN(std::make_shared(deserialize, s)); + } } public: @@ -289,6 +374,14 @@ class CDeterministicMNList { nHeight = _height; } + uint32_t GetTotalRegisteredCount() const + { + return nTotalRegisteredCount; + } + void SetTotalRegisteredCount(uint32_t _count) + { + nTotalRegisteredCount = _count; + } bool IsMNValid(const uint256& proTxHash) const; bool IsMNPoSeBanned(const uint256& proTxHash) const; @@ -318,6 +411,7 @@ class CDeterministicMNList CDeterministicMNCPtr GetValidMNByCollateral(const COutPoint& collateralOutpoint) const; CDeterministicMNCPtr GetMNByService(const CService& service) const; CDeterministicMNCPtr GetValidMNByService(const CService& service) const; + CDeterministicMNCPtr GetMNByInternalId(uint64_t internalId) const; CDeterministicMNCPtr GetMNPayee() const; /** @@ -372,10 +466,12 @@ class CDeterministicMNList CDeterministicMNListDiff BuildDiff(const CDeterministicMNList& to) const; CSimplifiedMNListDiff BuildSimplifiedDiff(const CDeterministicMNList& to) const; - CDeterministicMNList ApplyDiff(const CDeterministicMNListDiff& diff) const; + CDeterministicMNList ApplyDiff(const CBlockIndex* pindex, const CDeterministicMNListDiff& diff) const; void AddMN(const CDeterministicMNCPtr& dmn); + void UpdateMN(const CDeterministicMNCPtr& oldDmn, const CDeterministicMNStateCPtr& pdmnState); void UpdateMN(const uint256& proTxHash, const CDeterministicMNStateCPtr& pdmnState); + void UpdateMN(const CDeterministicMNCPtr& oldDmn, const CDeterministicMNStateDiff& stateDiff); void RemoveMN(const uint256& proTxHash); template @@ -445,25 +541,48 @@ class CDeterministicMNList class CDeterministicMNListDiff { public: - uint256 prevBlockHash; - uint256 blockHash; - int nHeight{-1}; - std::map addedMNs; - std::map updatedMNs; - std::set removedMns; + std::vector addedMNs; + // keys are all relating to the internalId of MNs + std::map updatedMNs; + std::set removedMns; public: - ADD_SERIALIZE_METHODS; + template + void Serialize(Stream& s) const + { + s << addedMNs; + WriteCompactSize(s, updatedMNs.size()); + for (const auto& p : updatedMNs) { + WriteVarInt(s, p.first); + s << p.second; + } + WriteCompactSize(s, removedMns.size()); + for (const auto& p : removedMns) { + WriteVarInt(s, p); + } + } - template - inline void SerializationOp(Stream& s, Operation ser_action) + template + void Unserialize(Stream& s) { - READWRITE(prevBlockHash); - READWRITE(blockHash); - READWRITE(nHeight); - READWRITE(addedMNs); - READWRITE(updatedMNs); - READWRITE(removedMns); + updatedMNs.clear(); + removedMns.clear(); + + size_t tmp; + uint64_t tmp2; + s >> addedMNs; + tmp = ReadCompactSize(s); + for (size_t i = 0; i < tmp; i++) { + CDeterministicMNStateDiff diff; + tmp2 = ReadVarInt(s); + s >> diff; + updatedMNs.emplace(tmp2, std::move(diff)); + } + tmp = ReadCompactSize(s); + for (size_t i = 0; i < tmp; i++) { + tmp2 = ReadVarInt(s); + removedMns.emplace(tmp2); + } } public: @@ -473,6 +592,37 @@ class CDeterministicMNListDiff } }; +// TODO can be removed in a future version +class CDeterministicMNListDiff_OldFormat +{ +public: + uint256 prevBlockHash; + uint256 blockHash; + int nHeight{-1}; + std::map addedMNs; + std::map updatedMNs; + std::set removedMns; + +public: + template + void Unserialize(Stream& s) { + addedMNs.clear(); + s >> prevBlockHash; + s >> blockHash; + s >> nHeight; + size_t cnt = ReadCompactSize(s); + for (size_t i = 0; i < cnt; i++) { + uint256 proTxHash; + auto dmn = std::make_shared(); + s >> proTxHash; + dmn->Unserialize(s, true); + addedMNs.emplace(proTxHash, dmn); + } + s >> updatedMNs; + s >> removedMns; + } +}; + class CDeterministicMNManager { static const int SNAPSHOT_LIST_PERIOD = 576; // once per day @@ -485,8 +635,7 @@ class CDeterministicMNManager CEvoDB& evoDb; std::map mnListsCache; - int tipHeight{-1}; - uint256 tipBlockHash; + const CBlockIndex* tipIndex{nullptr}; public: CDeterministicMNManager(CEvoDB& _evoDb); @@ -498,10 +647,10 @@ class CDeterministicMNManager // the returned list will not contain the correct block hash (we can't know it yet as the coinbase TX is not updated yet) bool BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, CValidationState& state, CDeterministicMNList& mnListRet, bool debugLogs); - void HandleQuorumCommitment(llmq::CFinalCommitment& qc, CDeterministicMNList& mnList, bool debugLogs); + void HandleQuorumCommitment(llmq::CFinalCommitment& qc, const CBlockIndex* pindexQuorum, CDeterministicMNList& mnList, bool debugLogs); void DecreasePoSePenalties(CDeterministicMNList& mnList); - CDeterministicMNList GetListForBlock(const uint256& blockHash); + CDeterministicMNList GetListForBlock(const CBlockIndex* pindex); CDeterministicMNList GetListAtChainTip(); // Test if given TX is a ProRegTx which also contains the collateral at index n @@ -509,6 +658,11 @@ class CDeterministicMNManager bool IsDIP3Enforced(int nHeight = -1); +public: + // TODO these can all be removed in a future version + bool UpgradeDiff(CDBBatch& batch, const CBlockIndex* pindexNext, const CDeterministicMNList& curMNList, CDeterministicMNList& newMNList); + void UpgradeDBIfNeeded(); + private: void CleanupCache(int nHeight); }; diff --git a/src/evo/evodb.h b/src/evo/evodb.h index 7772f6b06310..35b94186d3b8 100644 --- a/src/evo/evodb.h +++ b/src/evo/evodb.h @@ -9,7 +9,9 @@ #include "sync.h" #include "uint256.h" -static const std::string EVODB_BEST_BLOCK = "b_b"; +// "b_b" was used in the initial version of deterministic MN storage +// "b_b2" was used after compact diffs were introduced +static const std::string EVODB_BEST_BLOCK = "b_b2"; class CEvoDB { diff --git a/src/evo/mnauth.cpp b/src/evo/mnauth.cpp index f8a6de9ec7f5..19211884e77a 100644 --- a/src/evo/mnauth.cpp +++ b/src/evo/mnauth.cpp @@ -127,13 +127,17 @@ void CMNAuth::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& if (pnode->verifiedProRegTxHash.IsNull()) { return; } + auto verifiedDmn = oldMNList.GetMN(pnode->verifiedProRegTxHash); + if (!verifiedDmn) { + return; + } bool doRemove = false; - if (diff.removedMns.count(pnode->verifiedProRegTxHash)) { + if (diff.removedMns.count(verifiedDmn->internalId)) { doRemove = true; } else { - auto it = diff.updatedMNs.find(pnode->verifiedProRegTxHash); + auto it = diff.updatedMNs.find(verifiedDmn->internalId); if (it != diff.updatedMNs.end()) { - if (it->second->pubKeyOperator.GetHash() != pnode->verifiedPubKeyHash) { + if ((it->second.fields & CDeterministicMNStateDiff::Field_pubKeyOperator) && it->second.state.pubKeyOperator.GetHash() != pnode->verifiedPubKeyHash) { doRemove = true; } } diff --git a/src/evo/providertx.cpp b/src/evo/providertx.cpp index 2dca75bc6230..688f8abe371c 100644 --- a/src/evo/providertx.cpp +++ b/src/evo/providertx.cpp @@ -174,7 +174,7 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid } if (pindexPrev) { - auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash()); + auto mnList = deterministicMNManager->GetListForBlock(pindexPrev); // only allow reusing of addresses when it's for the same collateral (which replaces the old MN) if (mnList.HasUniqueProperty(ptx.addr) && mnList.GetUniquePropertyMN(ptx.addr)->collateralOutpoint != collateralOutpoint) { @@ -232,7 +232,7 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa } if (pindexPrev) { - auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash()); + auto mnList = deterministicMNManager->GetListForBlock(pindexPrev); auto mn = mnList.GetMN(ptx.proTxHash); if (!mn) { return state.DoS(100, false, REJECT_INVALID, "bad-protx-hash"); @@ -297,7 +297,7 @@ bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal } if (pindexPrev) { - auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash()); + auto mnList = deterministicMNManager->GetListForBlock(pindexPrev); auto dmn = mnList.GetMN(ptx.proTxHash); if (!dmn) { return state.DoS(100, false, REJECT_INVALID, "bad-protx-hash"); @@ -369,7 +369,7 @@ bool CheckProUpRevTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal } if (pindexPrev) { - auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash()); + auto mnList = deterministicMNManager->GetListForBlock(pindexPrev); auto dmn = mnList.GetMN(ptx.proTxHash); if (!dmn) return state.DoS(100, false, REJECT_INVALID, "bad-protx-hash"); diff --git a/src/evo/providertx.h b/src/evo/providertx.h index d7526ed60195..1e7218d540d0 100644 --- a/src/evo/providertx.h +++ b/src/evo/providertx.h @@ -50,7 +50,7 @@ class CProRegTx READWRITE(pubKeyOperator); READWRITE(keyIDVoting); READWRITE(nOperatorReward); - READWRITE(*(CScriptBase*)(&scriptPayout)); + READWRITE(scriptPayout); READWRITE(inputsHash); if (!(s.GetType() & SER_GETHASH)) { READWRITE(vchSig); @@ -108,7 +108,7 @@ class CProUpServTx READWRITE(nVersion); READWRITE(proTxHash); READWRITE(addr); - READWRITE(*(CScriptBase*)(&scriptOperatorPayout)); + READWRITE(scriptOperatorPayout); READWRITE(inputsHash); if (!(s.GetType() & SER_GETHASH)) { READWRITE(sig); @@ -160,7 +160,7 @@ class CProUpRegTx READWRITE(nMode); READWRITE(pubKeyOperator); READWRITE(keyIDVoting); - READWRITE(*(CScriptBase*)(&scriptPayout)); + READWRITE(scriptPayout); READWRITE(inputsHash); if (!(s.GetType() & SER_GETHASH)) { READWRITE(vchSig); diff --git a/src/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index 10c0d59b4c84..db272d02e0a0 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -217,10 +217,15 @@ bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& bloc LOCK(deterministicMNManager->cs); - auto baseDmnList = deterministicMNManager->GetListForBlock(baseBlockHash); - auto dmnList = deterministicMNManager->GetListForBlock(blockHash); + auto baseDmnList = deterministicMNManager->GetListForBlock(baseBlockIndex); + auto dmnList = deterministicMNManager->GetListForBlock(blockIndex); mnListDiffRet = baseDmnList.BuildSimplifiedDiff(dmnList); + // We need to return the value that was provided by the other peer as it otherwise won't be able to recognize the + // response. This will usually be identical to the block found in baseBlockIndex. The only difference is when a + // null block hash was provided to get the diff from the genesis block. + mnListDiffRet.baseBlockHash = baseBlockHash; + if (!mnListDiffRet.BuildQuorumsDiff(baseBlockIndex, blockIndex)) { errorRet = strprintf("failed to build quorums diff"); return false; diff --git a/src/governance/governance.cpp b/src/governance/governance.cpp index 18155ca7abbb..d83f1bfaaa61 100644 --- a/src/governance/governance.cpp +++ b/src/governance/governance.cpp @@ -24,7 +24,7 @@ CGovernanceManager governance; int nSubmittedFinalBudget; -const std::string CGovernanceManager::SERIALIZATION_VERSION_STRING = "CGovernanceManager-Version-14"; +const std::string CGovernanceManager::SERIALIZATION_VERSION_STRING = "CGovernanceManager-Version-15"; const int CGovernanceManager::MAX_TIME_FUTURE_DEVIATION = 60 * 60; const int CGovernanceManager::RELIABLE_PROPAGATION_TIME = 60; @@ -1274,15 +1274,15 @@ void CGovernanceManager::RemoveInvalidVotes() std::vector changedKeyMNs; for (const auto& p : diff.updatedMNs) { - auto oldDmn = lastMNListForVotingKeys.GetMN(p.first); - if (p.second->keyIDVoting != oldDmn->pdmnState->keyIDVoting) { + auto oldDmn = lastMNListForVotingKeys.GetMNByInternalId(p.first); + if ((p.second.fields & CDeterministicMNStateDiff::Field_keyIDVoting) && p.second.state.keyIDVoting != oldDmn->pdmnState->keyIDVoting) { changedKeyMNs.emplace_back(oldDmn->collateralOutpoint); - } else if (p.second->pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) { + } else if ((p.second.fields & CDeterministicMNStateDiff::Field_pubKeyOperator) && p.second.state.pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) { changedKeyMNs.emplace_back(oldDmn->collateralOutpoint); } } - for (const auto& proTxHash : diff.removedMns) { - auto oldDmn = lastMNListForVotingKeys.GetMN(proTxHash); + for (const auto& id : diff.removedMns) { + auto oldDmn = lastMNListForVotingKeys.GetMNByInternalId(id); changedKeyMNs.emplace_back(oldDmn->collateralOutpoint); } diff --git a/src/governance/governance.h b/src/governance/governance.h index d9031cca939e..4a621f05842f 100644 --- a/src/governance/governance.h +++ b/src/governance/governance.h @@ -339,7 +339,11 @@ class CGovernanceManager LOCK(cs); std::string strVersion; if (ser_action.ForRead()) { + Clear(); READWRITE(strVersion); + if (strVersion != SERIALIZATION_VERSION_STRING) { + return; + } } else { strVersion = SERIALIZATION_VERSION_STRING; READWRITE(strVersion); @@ -351,10 +355,6 @@ class CGovernanceManager READWRITE(mapObjects); READWRITE(mapLastMasternodeObject); READWRITE(lastMNListForVotingKeys); - if (ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) { - Clear(); - return; - } } void UpdatedBlockTip(const CBlockIndex* pindex, CConnman& connman); diff --git a/src/init.cpp b/src/init.cpp index 0712533ac7dc..9b96d849da92 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1863,6 +1863,8 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) break; } + deterministicMNManager->UpgradeDBIfNeeded(); + uiInterface.InitMessage(_("Verifying blocks...")); if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) { LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks", diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index c980e3021be7..17ace0cc39ce 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -49,10 +49,10 @@ CQuorum::~CQuorum() } } -void CQuorum::Init(const CFinalCommitment& _qc, int _height, const uint256& _minedBlockHash, const std::vector& _members) +void CQuorum::Init(const CFinalCommitment& _qc, const CBlockIndex* _pindexQuorum, const uint256& _minedBlockHash, const std::vector& _members) { qc = _qc; - height = _height; + pindexQuorum = _pindexQuorum; members = _members; minedBlockHash = _minedBlockHash; } @@ -193,9 +193,9 @@ void CQuorumManager::EnsureQuorumConnections(Consensus::LLMQType llmqType, const if (!g_connman->HasMasternodeQuorumNodes(llmqType, quorum->qc.quorumHash)) { std::set connections; if (quorum->IsMember(myProTxHash)) { - connections = CLLMQUtils::GetQuorumConnections(llmqType, quorum->qc.quorumHash, myProTxHash); + connections = CLLMQUtils::GetQuorumConnections(llmqType, quorum->pindexQuorum, myProTxHash); } else { - auto cindexes = CLLMQUtils::CalcDeterministicWatchConnections(llmqType, quorum->qc.quorumHash, quorum->members.size(), 1); + auto cindexes = CLLMQUtils::CalcDeterministicWatchConnections(llmqType, quorum->pindexQuorum, quorum->members.size(), 1); for (auto idx : cindexes) { connections.emplace(quorum->members[idx]->proTxHash); } @@ -231,9 +231,9 @@ bool CQuorumManager::BuildQuorumFromCommitment(const CFinalCommitment& qc, const assert(pindexQuorum); assert(qc.quorumHash == pindexQuorum->GetBlockHash()); - auto members = CLLMQUtils::GetAllQuorumMembers((Consensus::LLMQType)qc.llmqType, qc.quorumHash); + auto members = CLLMQUtils::GetAllQuorumMembers((Consensus::LLMQType)qc.llmqType, pindexQuorum); - quorum->Init(qc, pindexQuorum->nHeight, minedBlockHash, members); + quorum->Init(qc, pindexQuorum, minedBlockHash, members); bool hasValidVvec = false; if (quorum->ReadContributions(evoDb)) { @@ -262,7 +262,7 @@ bool CQuorumManager::BuildQuorumContributions(const CFinalCommitment& fqc, std:: std::vector memberIndexes; std::vector vvecs; BLSSecretKeyVector skContributions; - if (!dkgManager.GetVerifiedContributions((Consensus::LLMQType)fqc.llmqType, fqc.quorumHash, fqc.validMembers, memberIndexes, vvecs, skContributions)) { + if (!dkgManager.GetVerifiedContributions((Consensus::LLMQType)fqc.llmqType, quorum->pindexQuorum, fqc.validMembers, memberIndexes, vvecs, skContributions)) { return false; } diff --git a/src/llmq/quorums.h b/src/llmq/quorums.h index 8adaf5f44083..37da0f0d5f11 100644 --- a/src/llmq/quorums.h +++ b/src/llmq/quorums.h @@ -37,7 +37,7 @@ class CQuorum public: const Consensus::LLMQParams& params; CFinalCommitment qc; - int height; + const CBlockIndex* pindexQuorum; uint256 minedBlockHash; std::vector members; @@ -55,7 +55,7 @@ class CQuorum public: CQuorum(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker) : params(_params), blsCache(_blsWorker), stopCachePopulatorThread(false) {} ~CQuorum(); - void Init(const CFinalCommitment& _qc, int _height, const uint256& _minedBlockHash, const std::vector& _members); + void Init(const CFinalCommitment& _qc, const CBlockIndex* _pindexQuorum, const uint256& _minedBlockHash, const std::vector& _members); bool IsMember(const uint256& proTxHash) const; bool IsValidMember(const uint256& proTxHash) const; diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index a32c900eb163..fd6b84d2ce5e 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -57,6 +57,7 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC const auto& params = Params().GetConsensus().llmqs.at(type); // Verify that quorumHash is part of the active chain and that it's the first block in the DKG interval + const CBlockIndex* pquorumIndex; { LOCK(cs_main); if (!mapBlockIndex.count(qc.quorumHash)) { @@ -66,7 +67,7 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC // fully synced return; } - auto pquorumIndex = mapBlockIndex[qc.quorumHash]; + pquorumIndex = mapBlockIndex[qc.quorumHash]; if (chainActive.Tip()->GetAncestor(pquorumIndex->nHeight) != pquorumIndex) { LogPrintf("CQuorumBlockProcessor::%s -- block %s not in active chain, peer=%d\n", __func__, qc.quorumHash.ToString(), pfrom->GetId()); @@ -98,7 +99,7 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC } } - auto members = CLLMQUtils::GetAllQuorumMembers(type, qc.quorumHash); + auto members = CLLMQUtils::GetAllQuorumMembers(type, pquorumIndex); if (!qc.Verify(members, true)) { LOCK(cs_main); @@ -203,14 +204,14 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH return state.DoS(100, false, REJECT_INVALID, "bad-qc-height"); } - auto members = CLLMQUtils::GetAllQuorumMembers(params.type, quorumHash); + auto quorumIndex = mapBlockIndex.at(qc.quorumHash); + auto members = CLLMQUtils::GetAllQuorumMembers(params.type, quorumIndex); if (!qc.Verify(members, true)) { return state.DoS(100, false, REJECT_INVALID, "bad-qc-invalid"); } // Store commitment in DB - auto quorumIndex = mapBlockIndex.at(qc.quorumHash); evoDb.Write(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(params.type, quorumHash)), std::make_pair(qc, blockHash)); evoDb.Write(BuildInversedHeightKey(params.type, nHeight), quorumIndex->nHeight); diff --git a/src/llmq/quorums_commitment.cpp b/src/llmq/quorums_commitment.cpp index c75cd754b460..fd615c7cf8b7 100644 --- a/src/llmq/quorums_commitment.cpp +++ b/src/llmq/quorums_commitment.cpp @@ -169,7 +169,7 @@ bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, return true; } - auto members = CLLMQUtils::GetAllQuorumMembers(params.type, qcTx.commitment.quorumHash); + auto members = CLLMQUtils::GetAllQuorumMembers(params.type, pindexQuorum); if (!qcTx.commitment.Verify(members, false)) { return state.DoS(100, false, REJECT_INVALID, "bad-qc-invalid"); } diff --git a/src/llmq/quorums_debug.cpp b/src/llmq/quorums_debug.cpp index 2dec5c04e98a..e9bbcf9249ea 100644 --- a/src/llmq/quorums_debug.cpp +++ b/src/llmq/quorums_debug.cpp @@ -5,6 +5,7 @@ #include "quorums_debug.h" #include "chainparams.h" +#include "validation.h" #include "evo/deterministicmns.h" #include "quorums_utils.h" @@ -23,7 +24,17 @@ UniValue CDKGDebugSessionStatus::ToJson(int detailLevel) const std::vector dmnMembers; if (detailLevel == 2) { - dmnMembers = CLLMQUtils::GetAllQuorumMembers((Consensus::LLMQType) llmqType, quorumHash); + const CBlockIndex* pindex = nullptr; + { + LOCK(cs_main); + auto it = mapBlockIndex.find(quorumHash); + if (it != mapBlockIndex.end()) { + pindex = it->second; + } + } + if (pindex != nullptr) { + dmnMembers = CLLMQUtils::GetAllQuorumMembers((Consensus::LLMQType) llmqType, pindex); + } } ret.push_back(Pair("llmqType", llmqType)); diff --git a/src/llmq/quorums_dkgsession.cpp b/src/llmq/quorums_dkgsession.cpp index 036528bcd680..03e06b34f8fe 100644 --- a/src/llmq/quorums_dkgsession.cpp +++ b/src/llmq/quorums_dkgsession.cpp @@ -60,7 +60,7 @@ static bool ShouldSimulateError(const std::string& type) } CDKGLogger::CDKGLogger(const CDKGSession& _quorumDkg, const std::string& _func) : - CDKGLogger(_quorumDkg.params.type, _quorumDkg.quorumHash, _quorumDkg.height, _quorumDkg.AreWeMember(), _func) + CDKGLogger(_quorumDkg.params.type, _quorumDkg.pindexQuorum->GetBlockHash(), _quorumDkg.pindexQuorum->nHeight, _quorumDkg.AreWeMember(), _func) { } @@ -88,14 +88,13 @@ CDKGMember::CDKGMember(CDeterministicMNCPtr _dmn, size_t _idx) : } -bool CDKGSession::Init(int _height, const uint256& _quorumHash, const std::vector& mns, const uint256& _myProTxHash) +bool CDKGSession::Init(const CBlockIndex* _pindexQuorum, const std::vector& mns, const uint256& _myProTxHash) { if (mns.size() < params.minSize) { return false; } - height = _height; - quorumHash = _quorumHash; + pindexQuorum = _pindexQuorum; members.resize(mns.size()); memberIds.resize(members.size()); @@ -121,7 +120,7 @@ bool CDKGSession::Init(int _height, const uint256& _quorumHash, const std::vecto } if (!myProTxHash.IsNull()) { - quorumDKGDebugManager->InitLocalSessionStatus(params.type, quorumHash, height); + quorumDKGDebugManager->InitLocalSessionStatus(params.type, pindexQuorum->GetBlockHash(), pindexQuorum->nHeight); } CDKGLogger logger(*this, __func__); @@ -170,7 +169,7 @@ void CDKGSession::SendContributions(CDKGPendingMessages& pendingMessages) CDKGContribution qc; qc.llmqType = params.type; - qc.quorumHash = quorumHash; + qc.quorumHash = pindexQuorum->GetBlockHash(); qc.proTxHash = myProTxHash; qc.vvec = vvecContribution; @@ -216,7 +215,7 @@ bool CDKGSession::PreVerifyMessage(const uint256& hash, const CDKGContribution& retBan = false; - if (qc.quorumHash != quorumHash) { + if (qc.quorumHash != pindexQuorum->GetBlockHash()) { logger.Batch("contribution for wrong quorum, rejecting"); return false; } @@ -316,7 +315,7 @@ void CDKGSession::ReceiveMessage(const uint256& hash, const CDKGContribution& qc return; } - dkgManager.WriteVerifiedVvecContribution(params.type, qc.quorumHash, qc.proTxHash, qc.vvec); + dkgManager.WriteVerifiedVvecContribution(params.type, pindexQuorum, qc.proTxHash, qc.vvec); bool complain = false; CBLSSecretKey skContribution; @@ -398,7 +397,7 @@ void CDKGSession::VerifyPendingContributions() }); } else { size_t memberIdx = memberIndexes[i]; - dkgManager.WriteVerifiedSkContribution(params.type, quorumHash, members[memberIdx]->dmn->proTxHash, skContributions[i]); + dkgManager.WriteVerifiedSkContribution(params.type, pindexQuorum, members[memberIdx]->dmn->proTxHash, skContributions[i]); } } @@ -449,7 +448,7 @@ void CDKGSession::SendComplaint(CDKGPendingMessages& pendingMessages) CDKGComplaint qc(params); qc.llmqType = params.type; - qc.quorumHash = quorumHash; + qc.quorumHash = pindexQuorum->GetBlockHash(); qc.proTxHash = myProTxHash; int badCount = 0; @@ -490,7 +489,7 @@ bool CDKGSession::PreVerifyMessage(const uint256& hash, const CDKGComplaint& qc, retBan = false; - if (qc.quorumHash != quorumHash) { + if (qc.quorumHash != pindexQuorum->GetBlockHash()) { logger.Batch("complaint for wrong quorum, rejecting"); return false; } @@ -643,7 +642,7 @@ void CDKGSession::SendJustification(CDKGPendingMessages& pendingMessages, const CDKGJustification qj; qj.llmqType = params.type; - qj.quorumHash = quorumHash; + qj.quorumHash = pindexQuorum->GetBlockHash(); qj.proTxHash = myProTxHash; qj.contributions.reserve(forMembers.size()); @@ -688,7 +687,7 @@ bool CDKGSession::PreVerifyMessage(const uint256& hash, const CDKGJustification& retBan = false; - if (qj.quorumHash != quorumHash) { + if (qj.quorumHash != pindexQuorum->GetBlockHash()) { logger.Batch("justification for wrong quorum, rejecting"); return false; } @@ -824,7 +823,7 @@ void CDKGSession::ReceiveMessage(const uint256& hash, const CDKGJustification& q receivedSkContributions[member->idx] = skContribution; member->weComplain = false; - dkgManager.WriteVerifiedSkContribution(params.type, quorumHash, member->dmn->proTxHash, skContribution); + dkgManager.WriteVerifiedSkContribution(params.type, pindexQuorum, member->dmn->proTxHash, skContribution); } member->complaintsFromOthers.erase(member2->dmn->proTxHash); } @@ -899,7 +898,7 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages) CDKGPrematureCommitment qc(params); qc.llmqType = params.type; - qc.quorumHash = quorumHash; + qc.quorumHash = pindexQuorum->GetBlockHash(); qc.proTxHash = myProTxHash; for (size_t i = 0; i < members.size(); i++) { @@ -925,7 +924,7 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages) std::vector memberIndexes; std::vector vvecs; BLSSecretKeyVector skContributions; - if (!dkgManager.GetVerifiedContributions(params.type, quorumHash, qc.validMembers, memberIndexes, vvecs, skContributions)) { + if (!dkgManager.GetVerifiedContributions(params.type, pindexQuorum, qc.validMembers, memberIndexes, vvecs, skContributions)) { logger.Batch("failed to get valid contributions"); return; } @@ -1012,7 +1011,7 @@ bool CDKGSession::PreVerifyMessage(const uint256& hash, const CDKGPrematureCommi retBan = false; - if (qc.quorumHash != quorumHash) { + if (qc.quorumHash != pindexQuorum->GetBlockHash()) { logger.Batch("commitment for wrong quorum, rejecting"); return false; } @@ -1091,7 +1090,7 @@ void CDKGSession::ReceiveMessage(const uint256& hash, const CDKGPrematureCommitm std::vector vvecs; BLSSecretKeyVector skContributions; BLSVerificationVectorPtr quorumVvec; - if (dkgManager.GetVerifiedContributions(params.type, qc.quorumHash, qc.validMembers, memberIndexes, vvecs, skContributions)) { + if (dkgManager.GetVerifiedContributions(params.type, pindexQuorum, qc.validMembers, memberIndexes, vvecs, skContributions)) { quorumVvec = cache.BuildQuorumVerificationVector(::SerializeHash(memberIndexes), vvecs); } diff --git a/src/llmq/quorums_dkgsession.h b/src/llmq/quorums_dkgsession.h index 489d3121c017..28b64ff3d29e 100644 --- a/src/llmq/quorums_dkgsession.h +++ b/src/llmq/quorums_dkgsession.h @@ -249,8 +249,7 @@ class CDKGSession CBLSWorkerCache cache; CDKGSessionManager& dkgManager; - uint256 quorumHash; - int height{-1}; + const CBlockIndex* pindexQuorum; private: std::vector> members; @@ -287,7 +286,7 @@ class CDKGSession CDKGSession(const Consensus::LLMQParams& _params, CBLSWorker& _blsWorker, CDKGSessionManager& _dkgManager) : params(_params), blsWorker(_blsWorker), cache(_blsWorker), dkgManager(_dkgManager) {} - bool Init(int _height, const uint256& _quorumHash, const std::vector& mns, const uint256& _myProTxHash); + bool Init(const CBlockIndex* pindexQuorum, const std::vector& mns, const uint256& _myProTxHash); size_t GetMyMemberIndex() const { return myIdx; } diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index b54561ccf9e6..932881a06203 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -139,7 +139,7 @@ void CDKGSessionHandler::ProcessMessage(CNode* pfrom, const std::string& strComm } } -bool CDKGSessionHandler::InitNewQuorum(int newQuorumHeight, const uint256& newQuorumHash) +bool CDKGSessionHandler::InitNewQuorum(const CBlockIndex* pindexQuorum) { //AssertLockHeld(cs_main); @@ -147,13 +147,13 @@ bool CDKGSessionHandler::InitNewQuorum(int newQuorumHeight, const uint256& newQu curSession = std::make_shared(params, blsWorker, dkgManager); - if (!deterministicMNManager->IsDIP3Enforced(newQuorumHeight)) { + if (!deterministicMNManager->IsDIP3Enforced(pindexQuorum->nHeight)) { return false; } - auto mns = CLLMQUtils::GetAllQuorumMembers(params.type, newQuorumHash); + auto mns = CLLMQUtils::GetAllQuorumMembers(params.type, pindexQuorum); - if (!curSession->Init(newQuorumHeight, newQuorumHash, mns, activeMasternodeInfo.proTxHash)) { + if (!curSession->Init(pindexQuorum, mns, activeMasternodeInfo.proTxHash)) { LogPrintf("CDKGSessionManager::%s -- quorum initialiation failed\n", __func__); return false; } @@ -455,7 +455,13 @@ void CDKGSessionHandler::HandleDKGRound() curQuorumHeight = quorumHeight; } - if (!InitNewQuorum(curQuorumHeight, curQuorumHash)) { + const CBlockIndex* pindexQuorum; + { + LOCK(cs_main); + pindexQuorum = mapBlockIndex.at(curQuorumHash); + } + + if (!InitNewQuorum(pindexQuorum)) { // should actually never happen WaitForNewQuorum(curQuorumHash); throw AbortPhaseException(); @@ -470,16 +476,16 @@ void CDKGSessionHandler::HandleDKGRound() if (curSession->AreWeMember() || gArgs.GetBoolArg("-watchquorums", DEFAULT_WATCH_QUORUMS)) { std::set connections; if (curSession->AreWeMember()) { - connections = CLLMQUtils::GetQuorumConnections(params.type, curQuorumHash, curSession->myProTxHash); + connections = CLLMQUtils::GetQuorumConnections(params.type, pindexQuorum, curSession->myProTxHash); } else { - auto cindexes = CLLMQUtils::CalcDeterministicWatchConnections(params.type, curQuorumHash, curSession->members.size(), 1); + auto cindexes = CLLMQUtils::CalcDeterministicWatchConnections(params.type, pindexQuorum, curSession->members.size(), 1); for (auto idx : cindexes) { connections.emplace(curSession->members[idx]->dmn->proTxHash); } } if (!connections.empty()) { if (LogAcceptCategory(BCLog::LLMQ_DKG)) { - std::string debugMsg = strprintf("CDKGSessionManager::%s -- adding masternodes quorum connections for quorum %s:\n", __func__, curSession->quorumHash.ToString()); + std::string debugMsg = strprintf("CDKGSessionManager::%s -- adding masternodes quorum connections for quorum %s:\n", __func__, curSession->pindexQuorum->GetBlockHash().ToString()); auto mnList = deterministicMNManager->GetListAtChainTip(); for (const auto& c : connections) { auto dmn = mnList.GetValidMN(c); diff --git a/src/llmq/quorums_dkgsessionhandler.h b/src/llmq/quorums_dkgsessionhandler.h index c297057e9c2a..6613d06b324e 100644 --- a/src/llmq/quorums_dkgsessionhandler.h +++ b/src/llmq/quorums_dkgsessionhandler.h @@ -125,7 +125,7 @@ class CDKGSessionHandler void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman); private: - bool InitNewQuorum(int newQuorumHeight, const uint256& newQuorumHash); + bool InitNewQuorum(const CBlockIndex* pindexQuorum); std::pair GetPhaseAndQuorumHash() const; diff --git a/src/llmq/quorums_dkgsessionmgr.cpp b/src/llmq/quorums_dkgsessionmgr.cpp index 2370e931085c..2441e2aaa4f7 100644 --- a/src/llmq/quorums_dkgsessionmgr.cpp +++ b/src/llmq/quorums_dkgsessionmgr.cpp @@ -198,19 +198,19 @@ bool CDKGSessionManager::GetPrematureCommitment(const uint256& hash, CDKGPrematu return false; } -void CDKGSessionManager::WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& proTxHash, const BLSVerificationVectorPtr& vvec) +void CDKGSessionManager::WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const BLSVerificationVectorPtr& vvec) { - llmqDb.Write(std::make_tuple(DB_VVEC, llmqType, quorumHash, proTxHash), *vvec); + llmqDb.Write(std::make_tuple(DB_VVEC, llmqType, pindexQuorum->GetBlockHash(), proTxHash), *vvec); } -void CDKGSessionManager::WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& proTxHash, const CBLSSecretKey& skContribution) +void CDKGSessionManager::WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const CBLSSecretKey& skContribution) { - llmqDb.Write(std::make_tuple(DB_SKCONTRIB, llmqType, quorumHash, proTxHash), skContribution); + llmqDb.Write(std::make_tuple(DB_SKCONTRIB, llmqType, pindexQuorum->GetBlockHash(), proTxHash), skContribution); } -bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::vector& validMembers, std::vector& memberIndexesRet, std::vector& vvecsRet, BLSSecretKeyVector& skContributionsRet) +bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const std::vector& validMembers, std::vector& memberIndexesRet, std::vector& vvecsRet, BLSSecretKeyVector& skContributionsRet) { - auto members = CLLMQUtils::GetAllQuorumMembers(llmqType, quorumHash); + auto members = CLLMQUtils::GetAllQuorumMembers(llmqType, pindexQuorum); memberIndexesRet.clear(); vvecsRet.clear(); @@ -222,7 +222,7 @@ bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, if (validMembers[i]) { BLSVerificationVectorPtr vvec; CBLSSecretKey skContribution; - if (!GetVerifiedContribution(llmqType, quorumHash, members[i]->proTxHash, vvec, skContribution)) { + if (!GetVerifiedContribution(llmqType, pindexQuorum, members[i]->proTxHash, vvec, skContribution)) { return false; } @@ -234,10 +234,10 @@ bool CDKGSessionManager::GetVerifiedContributions(Consensus::LLMQType llmqType, return true; } -bool CDKGSessionManager::GetVerifiedContribution(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& proTxHash, BLSVerificationVectorPtr& vvecRet, CBLSSecretKey& skContributionRet) +bool CDKGSessionManager::GetVerifiedContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, BLSVerificationVectorPtr& vvecRet, CBLSSecretKey& skContributionRet) { LOCK(contributionsCacheCs); - ContributionsCacheKey cacheKey = {llmqType, quorumHash, proTxHash}; + ContributionsCacheKey cacheKey = {llmqType, pindexQuorum->GetBlockHash(), proTxHash}; auto it = contributionsCache.find(cacheKey); if (it != contributionsCache.end()) { vvecRet = it->second.vvec; @@ -248,10 +248,10 @@ bool CDKGSessionManager::GetVerifiedContribution(Consensus::LLMQType llmqType, c BLSVerificationVector vvec; BLSVerificationVectorPtr vvecPtr; CBLSSecretKey skContribution; - if (llmqDb.Read(std::make_tuple(DB_VVEC, llmqType, quorumHash, proTxHash), vvec)) { + if (llmqDb.Read(std::make_tuple(DB_VVEC, llmqType, pindexQuorum->GetBlockHash(), proTxHash), vvec)) { vvecPtr = std::make_shared(std::move(vvec)); } - llmqDb.Read(std::make_tuple(DB_SKCONTRIB, llmqType, quorumHash, proTxHash), skContribution); + llmqDb.Read(std::make_tuple(DB_SKCONTRIB, llmqType, pindexQuorum->GetBlockHash(), proTxHash), skContribution); it = contributionsCache.emplace(cacheKey, ContributionsCacheEntry{GetTimeMillis(), vvecPtr, skContribution}).first; diff --git a/src/llmq/quorums_dkgsessionmgr.h b/src/llmq/quorums_dkgsessionmgr.h index d943f25a2600..7c5074dd63a1 100644 --- a/src/llmq/quorums_dkgsessionmgr.h +++ b/src/llmq/quorums_dkgsessionmgr.h @@ -63,10 +63,10 @@ class CDKGSessionManager bool GetPrematureCommitment(const uint256& hash, CDKGPrematureCommitment& ret) const; // Verified contributions are written while in the DKG - void WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& proTxHash, const BLSVerificationVectorPtr& vvec); - void WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& proTxHash, const CBLSSecretKey& skContribution); - bool GetVerifiedContributions(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::vector& validMembers, std::vector& memberIndexesRet, std::vector& vvecsRet, BLSSecretKeyVector& skContributionsRet); - bool GetVerifiedContribution(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& proTxHash, BLSVerificationVectorPtr& vvecRet, CBLSSecretKey& skContributionRet); + void WriteVerifiedVvecContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const BLSVerificationVectorPtr& vvec); + void WriteVerifiedSkContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, const CBLSSecretKey& skContribution); + bool GetVerifiedContributions(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const std::vector& validMembers, std::vector& memberIndexesRet, std::vector& vvecsRet, BLSSecretKeyVector& skContributionsRet); + bool GetVerifiedContribution(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& proTxHash, BLSVerificationVectorPtr& vvecRet, CBLSSecretKey& skContributionRet); private: void CleanupCache(); diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index 2b48d0796389..87a85e9e55ae 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -12,11 +12,11 @@ namespace llmq { -std::vector CLLMQUtils::GetAllQuorumMembers(Consensus::LLMQType llmqType, const uint256& blockHash) +std::vector CLLMQUtils::GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum) { auto& params = Params().GetConsensus().llmqs.at(llmqType); - auto allMns = deterministicMNManager->GetListForBlock(blockHash); - auto modifier = ::SerializeHash(std::make_pair(llmqType, blockHash)); + auto allMns = deterministicMNManager->GetListForBlock(pindexQuorum); + auto modifier = ::SerializeHash(std::make_pair(llmqType, pindexQuorum->GetBlockHash())); return allMns.CalculateQuorum(params.size, modifier); } @@ -41,11 +41,11 @@ uint256 CLLMQUtils::BuildSignHash(Consensus::LLMQType llmqType, const uint256& q return h.GetHash(); } -std::set CLLMQUtils::GetQuorumConnections(Consensus::LLMQType llmqType, const uint256& blockHash, const uint256& forMember) +std::set CLLMQUtils::GetQuorumConnections(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& forMember) { auto& params = Params().GetConsensus().llmqs.at(llmqType); - auto mns = GetAllQuorumMembers(llmqType, blockHash); + auto mns = GetAllQuorumMembers(llmqType, pindexQuorum); std::set result; for (size_t i = 0; i < mns.size(); i++) { auto& dmn = mns[i]; @@ -73,7 +73,7 @@ std::set CLLMQUtils::GetQuorumConnections(Consensus::LLMQType llmqType, return result; } -std::set CLLMQUtils::CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, const uint256& blockHash, size_t memberCount, size_t connectionCount) +std::set CLLMQUtils::CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, size_t memberCount, size_t connectionCount) { static uint256 qwatchConnectionSeed; static std::atomic qwatchConnectionSeedGenerated{false}; @@ -89,7 +89,7 @@ std::set CLLMQUtils::CalcDeterministicWatchConnections(Consensus::LLMQTy std::set result; uint256 rnd = qwatchConnectionSeed; for (size_t i = 0; i < connectionCount; i++) { - rnd = ::SerializeHash(std::make_pair(rnd, std::make_pair(llmqType, blockHash))); + rnd = ::SerializeHash(std::make_pair(rnd, std::make_pair(llmqType, pindexQuorum->GetBlockHash()))); result.emplace(rnd.GetUint64(0) % memberCount); } return result; diff --git a/src/llmq/quorums_utils.h b/src/llmq/quorums_utils.h index 0a6fd40ff40f..7aaf70ad8484 100644 --- a/src/llmq/quorums_utils.h +++ b/src/llmq/quorums_utils.h @@ -19,7 +19,7 @@ class CLLMQUtils { public: // includes members which failed DKG - static std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, const uint256& blockHash); + static std::vector GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum); static uint256 BuildCommitmentHash(Consensus::LLMQType llmqType, const uint256& blockHash, const std::vector& validMembers, const CBLSPublicKey& pubKey, const uint256& vvecHash); static uint256 BuildSignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash); @@ -31,8 +31,8 @@ class CLLMQUtils return BuildSignHash((Consensus::LLMQType)s.llmqType, s.quorumHash, s.id, s.msgHash); } - static std::set GetQuorumConnections(Consensus::LLMQType llmqType, const uint256& blockHash, const uint256& forMember); - static std::set CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, const uint256& blockHash, size_t memberCount, size_t connectionCount); + static std::set GetQuorumConnections(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& forMember); + static std::set CalcDeterministicWatchConnections(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, size_t memberCount, size_t connectionCount); static bool IsQuorumActive(Consensus::LLMQType llmqType, const uint256& quorumHash); diff --git a/src/masternode/activemasternode.cpp b/src/masternode/activemasternode.cpp index e0278b761ec4..a5eb145cefe6 100644 --- a/src/masternode/activemasternode.cpp +++ b/src/masternode/activemasternode.cpp @@ -134,7 +134,7 @@ void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, con if (!deterministicMNManager->IsDIP3Enforced(pindexNew->nHeight)) return; if (state == MASTERNODE_READY) { - auto mnList = deterministicMNManager->GetListForBlock(pindexNew->GetBlockHash()); + auto mnList = deterministicMNManager->GetListForBlock(pindexNew); if (!mnList.IsMNValid(mnListEntry->proTxHash)) { // MN disappeared from MN list state = MASTERNODE_REMOVED; diff --git a/src/masternode/masternode-meta.cpp b/src/masternode/masternode-meta.cpp index 18f07f1beb9d..9ec37b9e247f 100644 --- a/src/masternode/masternode-meta.cpp +++ b/src/masternode/masternode-meta.cpp @@ -118,7 +118,6 @@ 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/masternode-meta.h b/src/masternode/masternode-meta.h index 8ef5c753fe6b..fe4104611d44 100644 --- a/src/masternode/masternode-meta.h +++ b/src/masternode/masternode-meta.h @@ -100,7 +100,11 @@ class CMasternodeMetaMan std::string strVersion; if(ser_action.ForRead()) { + Clear(); READWRITE(strVersion); + if (strVersion != SERIALIZATION_VERSION_STRING) { + return; + } } else { strVersion = SERIALIZATION_VERSION_STRING; @@ -122,10 +126,6 @@ class CMasternodeMetaMan } READWRITE(nDsqCount); - - if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) { - Clear(); - } } public: diff --git a/src/masternode/masternode-payments.cpp b/src/masternode/masternode-payments.cpp index 6a23b22d85f9..cdccbd0f2e16 100644 --- a/src/masternode/masternode-payments.cpp +++ b/src/masternode/masternode-payments.cpp @@ -271,7 +271,7 @@ std::map GetRequiredPaymentsStrings(int nStartHeight, int nEnd bool doProjection = false; for(int h = nStartHeight; h < nEndHeight; h++) { if (h <= nChainTipHeight) { - auto payee = deterministicMNManager->GetListForBlock(chainActive[h - 1]->GetBlockHash()).GetMNPayee(); + auto payee = deterministicMNManager->GetListForBlock(chainActive[h - 1]).GetMNPayee(); mapPayments.emplace(h, GetRequiredPaymentsString(h, payee)); } else { doProjection = true; @@ -323,13 +323,13 @@ bool CMasternodePayments::GetBlockTxOuts(int nBlockHeight, CAmount blockReward, CAmount masternodeReward = GetMasternodePayment(nBlockHeight, blockReward); - uint256 blockHash; + const CBlockIndex* pindex; { LOCK(cs_main); - blockHash = chainActive[nBlockHeight - 1]->GetBlockHash(); + pindex = chainActive[nBlockHeight - 1]; } uint256 proTxHash; - auto dmnPayee = deterministicMNManager->GetListForBlock(blockHash).GetMNPayee(); + auto dmnPayee = deterministicMNManager->GetListForBlock(pindex).GetMNPayee(); if (!dmnPayee) { return false; } diff --git a/src/rpc/rpcevo.cpp b/src/rpc/rpcevo.cpp index 4c5ed8468770..35913e245e16 100644 --- a/src/rpc/rpcevo.cpp +++ b/src/rpc/rpcevo.cpp @@ -972,7 +972,7 @@ UniValue protx_list(const JSONRPCRequest& request) setOutpts.emplace(outpt); } - CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(chainActive[height]->GetBlockHash()); + CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(chainActive[height]); mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) { if (setOutpts.count(dmn->collateralOutpoint) || CheckWalletOwnsKey(pwallet, dmn->pdmnState->keyIDOwner) || @@ -997,7 +997,7 @@ UniValue protx_list(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid height specified"); } - CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(chainActive[height]->GetBlockHash()); + CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(chainActive[height]); bool onlyValid = type == "valid"; mnList.ForEachMN(onlyValid, [&](const CDeterministicMNCPtr& dmn) { ret.push_back(BuildDMNListEntry(pwallet, dmn, detailed)); diff --git a/src/rpc/rpcquorums.cpp b/src/rpc/rpcquorums.cpp index b9709ef8c902..78ae2bb83757 100644 --- a/src/rpc/rpcquorums.cpp +++ b/src/rpc/rpcquorums.cpp @@ -80,7 +80,7 @@ UniValue BuildQuorumInfo(const llmq::CQuorumCPtr& quorum, bool includeMembers, b { UniValue ret(UniValue::VOBJ); - ret.push_back(Pair("height", quorum->height)); + ret.push_back(Pair("height", quorum->pindexQuorum->nHeight)); ret.push_back(Pair("type", quorum->params.name)); ret.push_back(Pair("quorumHash", quorum->qc.quorumHash.ToString())); ret.push_back(Pair("minedBlock", quorum->minedBlockHash.ToString())); @@ -222,7 +222,7 @@ UniValue quorum_memberof(const JSONRPCRequest& request) pindexTip = chainActive.Tip(); } - auto mnList = deterministicMNManager->GetListForBlock(pindexTip->GetBlockHash()); + auto mnList = deterministicMNManager->GetListForBlock(pindexTip); auto dmn = mnList.GetMN(protxHash); if (!dmn) { throw JSONRPCError(RPC_INVALID_PARAMETER, "masternode not found"); diff --git a/src/script/script.h b/src/script/script.h index 6a9f67d37fd3..9a276ed3fe1b 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -648,6 +648,15 @@ class CScript : public CScriptBase // The default std::vector::clear() does not release memory. CScriptBase().swap(*this); } + + template + void Serialize(Stream& s) const { + s << *(CScriptBase*)this; + } + template + void Unserialize(Stream& s) { + s >> *(CScriptBase*)this; + } }; class CReserveScript diff --git a/src/spentindex.h b/src/spentindex.h index f4628bb6c690..8d41f5d624ee 100644 --- a/src/spentindex.h +++ b/src/spentindex.h @@ -216,7 +216,7 @@ struct CAddressUnspentValue { template inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(satoshis); - READWRITE(*(CScriptBase*)(&script)); + READWRITE(script); READWRITE(blockHeight); } From 2f21e55514e5e8d8e8bd5b7b121fac8a92d39ed6 Mon Sep 17 00:00:00 2001 From: Alexander Block Date: Tue, 9 Jul 2019 16:50:08 +0200 Subject: [PATCH 365/987] Remove legacy InstantSend code (#3020) * Remove ppszTypeName from protocol.cpp and reimplement GetCommand This removes the need to carefully maintain ppszTypeName, which required correct order and also did not allow to permanently remove old message types. To get the command name for an INV type, GetCommandInternal uses a switch which needs to be maintained from now on. The way this is implemented also resembles the way it is implemented in Bitcoin today, but it's not identical. The original PR that introduced the switch case in Bitcoin was part of the Segwit changes and thus never got backported. I decided to implement it in a slightly different way that avoids throwing exceptions when an unknown INV type is encountered. IsKnownType will now also leverage GetCommandInternal() to figure out if the INV type is known locally. This has the side effect of old/legacy message types to return false from now on. We will depend on this side effect in later commits when we remove legacy InstantSend code. * Stop handling/relaying legacy IX messages When we receive an IX message, we simply treat it as a regular TX and relay it as such. We'll however still request IX messages when they are announced to us. We can't simply revert to requesting TX messages in this case as it might result in the other peer not answering due to the TX not being in mapRelay yet. We should at some point in the future completely drop handling of IX messages instead. * Remove IsNewInstantSendEnabled() and only use IsInstantSendEnabled() * Remove legacy InstantSend from GUI * Remove InstantSend from Bitcoin/Dash URIs * Remove legacy InstantSend from RPC commands * Remove legacy InstantSend from wallet * Remove legacy instantsend.h include * Remove legacy InstantSend from validation code * Completely remove remaining legacy InstantSend code * Remove now unused spork * Fix InstantSend related test failures * Remove now obsolete auto IS tests * Make spork2 and spork3 disabled by default This should have no influence on mainnet as these sporks are actually set there. This will however affect regtest, which shouldn't have LLMQ based InstantSend enabled by default. * Remove instantsend tests from dip3-deterministicmns.py These were only testing legacy InstantSend * Fix .QCheckBox#checkUsePrivateSend styling a bit * s/TXLEGACYLOCKREQUEST/LEGACYTXLOCKREQUEST/ * Revert "verified via InstantSend" back to "verified via LLMQ based InstantSend" * Use cmd == nullptr instead of !cmd * Remove last parameter from AvailableCoins call This was for fUseInstantSend which is not present anymore since rebase --- doc/files.md | 1 - src/Makefile.am | 2 - src/chainparams.cpp | 8 - src/consensus/params.h | 2 - src/dsnotificationinterface.cpp | 16 - src/init.cpp | 27 +- src/instantsend.cpp | 1264 ----------------- src/instantsend.h | 392 ----- src/llmq/quorums_chainlocks.cpp | 4 +- src/llmq/quorums_instantsend.cpp | 51 +- src/llmq/quorums_instantsend.h | 7 - src/net.cpp | 13 +- src/net_processing.cpp | 75 +- src/protocol.cpp | 102 +- src/protocol.h | 13 +- src/qt/coincontroldialog.cpp | 8 - src/qt/forms/receivecoinsdialog.ui | 14 +- src/qt/forms/sendcoinsdialog.ui | 16 - src/qt/guiutil.cpp | 11 +- src/qt/overviewpage.cpp | 1 - src/qt/receivecoinsdialog.cpp | 1 - src/qt/receiverequestdialog.cpp | 1 - src/qt/res/css/crownium.css | 10 - src/qt/res/css/drkblue.css | 10 - src/qt/res/css/light-hires-retro.css | 10 - src/qt/res/css/light-hires.css | 10 - src/qt/res/css/light-retro.css | 10 - src/qt/res/css/light.css | 10 - src/qt/res/css/trad.css | 5 - src/qt/sendcoinsdialog.cpp | 31 +- src/qt/sendcoinsdialog.h | 1 - src/qt/test/uritests.cpp | 17 +- src/qt/transactiondesc.cpp | 20 +- src/qt/walletmodel.cpp | 33 +- src/qt/walletmodel.h | 3 - src/rpc/blockchain.cpp | 5 +- src/rpc/governance.cpp | 8 +- src/rpc/rawtransaction.cpp | 17 +- src/rpc/rpcevo.cpp | 2 +- src/spork.cpp | 5 +- src/spork.h | 1 - src/txmempool.cpp | 13 +- src/txmempool.h | 2 - src/validation.cpp | 43 - src/wallet/coincontrol.h | 2 - src/wallet/rpcwallet.cpp | 103 +- src/wallet/wallet.cpp | 108 +- src/wallet/wallet.h | 15 +- src/zmq/zmqconfig.h | 2 - test/functional/autois-mempool.py | 123 -- test/functional/dip3-deterministicmns.py | 57 - test/functional/llmq-chainlocks.py | 7 +- test/functional/llmq-is-cl-conflicts.py | 3 +- test/functional/multikeysporks.py | 2 +- test/functional/p2p-autoinstantsend.py | 99 -- test/functional/p2p-instantsend.py | 15 +- test/functional/sporks.py | 16 +- .../test_framework/test_framework.py | 85 -- test/functional/test_runner.py | 2 - 59 files changed, 159 insertions(+), 2775 deletions(-) delete mode 100644 src/instantsend.cpp delete mode 100644 src/instantsend.h delete mode 100755 test/functional/autois-mempool.py delete mode 100755 test/functional/p2p-autoinstantsend.py diff --git a/doc/files.md b/doc/files.md index c295581569d2..0995b43b9808 100644 --- a/doc/files.md +++ b/doc/files.md @@ -12,7 +12,6 @@ * evodb/*: special txes and quorums database * fee_estimates.dat: stores statistics used to estimate minimum transaction fees and priorities required for confirmation * governance.dat: stores data for governance obgects -* instantsend.dat: stores data for instantsend locks * llmq/*: quorum signatures database * mempool.dat: dump of the mempool's transactions * mncache.dat: stores data for masternode list diff --git a/src/Makefile.am b/src/Makefile.am index d2c842e00ef1..57b9ccc4a839 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -153,7 +153,6 @@ BITCOIN_CORE_H = \ httpserver.h \ indirectmap.h \ init.h \ - instantsend.h \ key.h \ keepass.h \ keystore.h \ @@ -273,7 +272,6 @@ libdash_server_a_SOURCES = \ httprpc.cpp \ httpserver.cpp \ init.cpp \ - instantsend.cpp \ dbwrapper.cpp \ governance/governance.cpp \ governance/governance-classes.cpp \ diff --git a/src/chainparams.cpp b/src/chainparams.cpp index cc0752dec45e..de4a2fa3bb7d 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -227,8 +227,6 @@ class CMainParams : public CChainParams { consensus.nMasternodePaymentsIncreasePeriod = 576*30; // 17280 - actual historical value consensus.nInstantSendConfirmationsRequired = 6; consensus.nInstantSendKeepLock = 24; - consensus.nInstantSendSigsRequired = 6; - consensus.nInstantSendSigsTotal = 10; consensus.nBudgetPaymentsStartBlock = 328008; // actual historical value consensus.nBudgetPaymentsCycleBlocks = 16616; // ~(60*24*30)/2.6, actual number of blocks per month is 200700 / 12 = 16725 consensus.nBudgetPaymentsWindowBlocks = 100; @@ -409,8 +407,6 @@ class CTestNetParams : public CChainParams { consensus.nMasternodePaymentsIncreasePeriod = 10; consensus.nInstantSendConfirmationsRequired = 2; consensus.nInstantSendKeepLock = 6; - consensus.nInstantSendSigsRequired = 6; - consensus.nInstantSendSigsTotal = 10; consensus.nBudgetPaymentsStartBlock = 4100; consensus.nBudgetPaymentsCycleBlocks = 50; consensus.nBudgetPaymentsWindowBlocks = 10; @@ -568,8 +564,6 @@ class CDevNetParams : public CChainParams { consensus.nMasternodePaymentsIncreasePeriod = 10; consensus.nInstantSendConfirmationsRequired = 2; consensus.nInstantSendKeepLock = 6; - consensus.nInstantSendSigsRequired = 6; - consensus.nInstantSendSigsTotal = 10; consensus.nBudgetPaymentsStartBlock = 4100; consensus.nBudgetPaymentsCycleBlocks = 50; consensus.nBudgetPaymentsWindowBlocks = 10; @@ -734,8 +728,6 @@ class CRegTestParams : public CChainParams { consensus.nMasternodePaymentsIncreasePeriod = 10; consensus.nInstantSendConfirmationsRequired = 2; consensus.nInstantSendKeepLock = 6; - consensus.nInstantSendSigsRequired = 3; - consensus.nInstantSendSigsTotal = 5; consensus.nBudgetPaymentsStartBlock = 1000; consensus.nBudgetPaymentsCycleBlocks = 50; consensus.nBudgetPaymentsWindowBlocks = 10; diff --git a/src/consensus/params.h b/src/consensus/params.h index 7a589165a5fc..0e330e1fa2e4 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -125,8 +125,6 @@ struct Params { int nMasternodePaymentsIncreasePeriod; // in blocks int nInstantSendConfirmationsRequired; // in blocks int nInstantSendKeepLock; // in blocks - int nInstantSendSigsRequired; - int nInstantSendSigsTotal; int nBudgetPaymentsStartBlock; int nBudgetPaymentsCycleBlocks; int nBudgetPaymentsWindowBlocks; diff --git a/src/dsnotificationinterface.cpp b/src/dsnotificationinterface.cpp index 6113f5976ecc..2ff951afba83 100644 --- a/src/dsnotificationinterface.cpp +++ b/src/dsnotificationinterface.cpp @@ -4,7 +4,6 @@ #include "chainparams.h" #include "dsnotificationinterface.h" -#include "instantsend.h" #include "governance/governance.h" #include "masternode/masternode-payments.h" #include "masternode/masternode-sync.h" @@ -50,8 +49,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con // Update global DIP0001 activation status fDIP0001ActiveAtTip = pindexNew->nHeight >= Params().GetConsensus().DIP0001Height; - // update instantsend autolock activation flag (we reuse the DIP3 deployment) - instantsend.isAutoLockBip9Active = pindexNew->nHeight + 1 >= Params().GetConsensus().DIP0003Height; if (fInitialDownload) return; @@ -67,7 +64,6 @@ void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, con llmq::quorumInstantSendManager->UpdatedBlockTip(pindexNew); llmq::chainLocksHandler->UpdatedBlockTip(pindexNew); - instantsend.UpdatedBlockTip(pindexNew); governance.UpdatedBlockTip(pindexNew, connman); llmq::quorumManager->UpdatedBlockTip(pindexNew, fInitialDownload); llmq::quorumDKGSessionManager->UpdatedBlockTip(pindexNew, fInitialDownload); @@ -78,7 +74,6 @@ void CDSNotificationInterface::TransactionAddedToMempool(const CTransactionRef& llmq::quorumInstantSendManager->TransactionAddedToMempool(ptx); llmq::chainLocksHandler->TransactionAddedToMempool(ptx); CPrivateSend::TransactionAddedToMempool(ptx); - instantsend.SyncTransaction(ptx); } void CDSNotificationInterface::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) @@ -94,13 +89,6 @@ void CDSNotificationInterface::BlockConnected(const std::shared_ptrBlockConnected(pblock, pindex, vtxConflicted); llmq::chainLocksHandler->BlockConnected(pblock, pindex, vtxConflicted); CPrivateSend::BlockConnected(pblock, pindex, vtxConflicted); - - for (const CTransactionRef& ptx : vtxConflicted) { - instantsend.SyncTransaction(ptx); - } - for (size_t i = 0; i < pblock->vtx.size(); i++) { - instantsend.SyncTransaction(pblock->vtx[i], pindex, i); - } } void CDSNotificationInterface::BlockDisconnected(const std::shared_ptr& pblock, const CBlockIndex* pindexDisconnected) @@ -108,10 +96,6 @@ void CDSNotificationInterface::BlockDisconnected(const std::shared_ptrBlockDisconnected(pblock, pindexDisconnected); llmq::chainLocksHandler->BlockDisconnected(pblock, pindexDisconnected); CPrivateSend::BlockDisconnected(pblock, pindexDisconnected); - - for (const CTransactionRef& ptx : pblock->vtx) { - instantsend.SyncTransaction(ptx, pindexDisconnected->pprev, -1); - } } void CDSNotificationInterface::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) diff --git a/src/init.cpp b/src/init.cpp index 9b96d849da92..242be406398f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -52,7 +52,6 @@ #include "dsnotificationinterface.h" #include "flat-database.h" #include "governance/governance.h" -#include "instantsend.h" #ifdef ENABLE_WALLET #include "keepass.h" #endif @@ -267,11 +266,6 @@ void PrepareShutdown() flatdb3.Dump(governance); CFlatDB flatdb4("netfulfilled.dat", "magicFulfilledCache"); flatdb4.Dump(netfulfilledman); - if(fEnableInstantSend) - { - CFlatDB flatdb5("instantsend.dat", "magicInstantSendCache"); - flatdb5.Dump(instantsend); - } CFlatDB flatdb6("sporks.dat", "magicSporkCache"); flatdb6.Dump(sporkManager); } @@ -616,7 +610,6 @@ std::string HelpMessage(HelpMessageMode mode) #endif // ENABLE_WALLET strUsage += HelpMessageGroup(_("InstantSend options:")); - strUsage += HelpMessageOpt("-enableinstantsend", strprintf(_("Enable InstantSend, show confirmations for locked transactions (0-1, default: %u)"), 1)); strUsage += HelpMessageOpt("-instantsendnotify=", _("Execute command when a wallet InstantSend transaction is successfully locked (%s in cmd is replaced by TxID)")); @@ -2029,11 +2022,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) CPrivateSend::InitStandardDenominations(); - // ********************************************************* Step 10b: setup InstantSend - - fEnableInstantSend = gArgs.GetBoolArg("-enableinstantsend", 1); - - // ********************************************************* Step 10c: Load cache data + // ********************************************************* Step 10b: Load cache data // LOAD SERIALIZED DAT FILES INTO DATA CACHES FOR INTERNAL USE @@ -2063,27 +2052,15 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) if(!flatdb4.Load(netfulfilledman)) { return InitError(_("Failed to load fulfilled requests cache from") + "\n" + (pathDB / strDBName).string()); } - - if(fEnableInstantSend) - { - strDBName = "instantsend.dat"; - uiInterface.InitMessage(_("Loading InstantSend data cache...")); - CFlatDB flatdb5(strDBName, "magicInstantSendCache"); - if(!flatdb5.Load(instantsend)) { - return InitError(_("Failed to load InstantSend data cache from") + "\n" + (pathDB / strDBName).string()); - } - } } - // ********************************************************* Step 10d: schedule Dash-specific tasks + // ********************************************************* Step 10c: schedule Dash-specific tasks if (!fLiteMode) { scheduler.scheduleEvery(boost::bind(&CNetFulfilledRequestManager::DoMaintenance, boost::ref(netfulfilledman)), 60 * 1000); scheduler.scheduleEvery(boost::bind(&CMasternodeSync::DoMaintenance, boost::ref(masternodeSync), boost::ref(*g_connman)), 1 * 1000); scheduler.scheduleEvery(boost::bind(&CGovernanceManager::DoMaintenance, boost::ref(governance), boost::ref(*g_connman)), 60 * 5 * 1000); - - scheduler.scheduleEvery(boost::bind(&CInstantSend::DoMaintenance, boost::ref(instantsend)), 60 * 1000); } scheduler.scheduleEvery(boost::bind(&CMasternodeUtils::DoMaintenance, boost::ref(*g_connman)), 1 * 1000); diff --git a/src/instantsend.cpp b/src/instantsend.cpp deleted file mode 100644 index d8129659b4af..000000000000 --- a/src/instantsend.cpp +++ /dev/null @@ -1,1264 +0,0 @@ -// Copyright (c) 2014-2019 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/activemasternode.h" -#include "init.h" -#include "instantsend.h" -#include "key.h" -#include "validation.h" -#include "masternode/masternode-payments.h" -#include "masternode/masternode-sync.h" -#include "masternode/masternode-utils.h" -#include "messagesigner.h" -#include "net.h" -#include "netmessagemaker.h" -#include "protocol.h" -#include "spork.h" -#include "sync.h" -#include "txmempool.h" -#include "util.h" -#include "consensus/validation.h" -#include "validationinterface.h" -#include "warnings.h" -#ifdef ENABLE_WALLET -#include "wallet/wallet.h" -#endif // ENABLE_WALLET - -#include "llmq/quorums_instantsend.h" - -#include -#include - -#ifdef ENABLE_WALLET -extern CWallet* pwalletMain; -#endif // ENABLE_WALLET -extern CTxMemPool mempool; - -bool fEnableInstantSend = true; - -std::atomic CInstantSend::isAutoLockBip9Active{false}; -const double CInstantSend::AUTO_IX_MEMPOOL_THRESHOLD = 0.1; - -CInstantSend instantsend; -const std::string CInstantSend::SERIALIZATION_VERSION_STRING = "CInstantSend-Version-1"; - -// Transaction Locks -// -// step 1) Some node announces intention to lock transaction inputs via "txlockrequest" message (ix) -// step 2) Top nInstantSendSigsTotal masternodes per each spent outpoint push "txlockvote" message (txlvote) -// step 3) Once there are nInstantSendSigsRequired valid "txlockvote" messages (txlvote) per each spent outpoint -// for a corresponding "txlockrequest" message (ix), all outpoints from that tx are treated as locked - -// -// CInstantSend -// - -void CInstantSend::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman) -{ - if (fLiteMode) return; // disable all Dash specific functionality - if (!llmq::IsOldInstantSendEnabled()) return; - - // NOTE: NetMsgType::TXLOCKREQUEST is handled via ProcessMessage() in net_processing.cpp - - if (strCommand == NetMsgType::TXLOCKVOTE) { // InstantSend Transaction Lock Consensus Votes - if(pfrom->nVersion < MIN_INSTANTSEND_PROTO_VERSION) { - LogPrint(BCLog::INSTANTSEND, "TXLOCKVOTE -- peer=%d using obsolete version %i\n", pfrom->GetId(), pfrom->nVersion); - connman.PushMessage(pfrom, CNetMsgMaker(pfrom->GetSendVersion()).Make(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, - strprintf("Version must be %d or greater", MIN_INSTANTSEND_PROTO_VERSION))); - return; - } - - CTxLockVote vote; - vRecv >> vote; - - - uint256 nVoteHash = vote.GetHash(); - - { - LOCK(cs_main); - connman.RemoveAskFor(nVoteHash); - } - - // Ignore any InstantSend messages until blockchain is synced - if (!masternodeSync.IsBlockchainSynced()) return; - - { - LOCK(cs_instantsend); - auto ret = mapTxLockVotes.emplace(nVoteHash, vote); - if (!ret.second) return; - } - - ProcessNewTxLockVote(pfrom, vote, connman); - - return; - } -} - -bool CInstantSend::ProcessTxLockRequest(const CTxLockRequest& txLockRequest, CConnman& connman) -{ - LOCK(cs_main); -#ifdef ENABLE_WALLET - LOCK(pwalletMain ? &pwalletMain->cs_wallet : NULL); -#endif - LOCK2(mempool.cs, cs_instantsend); - - uint256 txHash = txLockRequest.GetHash(); - - // Check to see if we conflict with existing completed lock - for (const auto& txin : txLockRequest.tx->vin) { - std::map::iterator it = mapLockedOutpoints.find(txin.prevout); - if (it != mapLockedOutpoints.end() && it->second != txLockRequest.GetHash()) { - // Conflicting with complete lock, proceed to see if we should cancel them both - LogPrintf("CInstantSend::ProcessTxLockRequest -- WARNING: Found conflicting completed Transaction Lock, txid=%s, completed lock txid=%s\n", - txLockRequest.GetHash().ToString(), it->second.ToString()); - } - } - - // Check to see if there are votes for conflicting request, - // if so - do not fail, just warn user - for (const auto& txin : txLockRequest.tx->vin) { - std::map >::iterator it = mapVotedOutpoints.find(txin.prevout); - if (it != mapVotedOutpoints.end()) { - for (const auto& hash : it->second) { - if (hash != txLockRequest.GetHash()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::ProcessTxLockRequest -- Double spend attempt! %s\n", txin.prevout.ToStringShort()); - // do not fail here, let it go and see which one will get the votes to be locked - // NOTIFY ZMQ - CTransaction txCurrent = *txLockRequest.tx; // currently processed tx - auto itPrevious = mapTxLockCandidates.find(hash); - if (itPrevious != mapTxLockCandidates.end() && itPrevious->second.txLockRequest) { - CTransaction txPrevious = *itPrevious->second.txLockRequest.tx; // previously locked one - GetMainSignals().NotifyInstantSendDoubleSpendAttempt(txCurrent, txPrevious); - } - } - } - } - } - - if (!CreateTxLockCandidate(txLockRequest)) { - // smth is not right - LogPrintf("CInstantSend::ProcessTxLockRequest -- CreateTxLockCandidate failed, txid=%s\n", txHash.ToString()); - return false; - } - LogPrintf("CInstantSend::ProcessTxLockRequest -- accepted, txid=%s\n", txHash.ToString()); - - // Masternodes will sometimes propagate votes before the transaction is known to the client. - // If this just happened - process orphan votes, lock inputs, resolve conflicting locks, - // update transaction status forcing external script/zmq notifications. - ProcessOrphanTxLockVotes(); - std::map::iterator itLockCandidate = mapTxLockCandidates.find(txHash); - TryToFinalizeLockCandidate(itLockCandidate->second); - - return true; -} - -bool CInstantSend::CreateTxLockCandidate(const CTxLockRequest& txLockRequest) -{ - if (!txLockRequest.IsValid()) return false; - - LOCK(cs_instantsend); - - uint256 txHash = txLockRequest.GetHash(); - - std::map::iterator itLockCandidate = mapTxLockCandidates.find(txHash); - if (itLockCandidate == mapTxLockCandidates.end()) { - LogPrintf("CInstantSend::CreateTxLockCandidate -- new, txid=%s\n", txHash.ToString()); - - CTxLockCandidate txLockCandidate(txLockRequest); - // all inputs should already be checked by txLockRequest.IsValid() above, just use them now - for (const auto& txin : txLockRequest.tx->vin) { - txLockCandidate.AddOutPointLock(txin.prevout); - } - mapTxLockCandidates.insert(std::make_pair(txHash, txLockCandidate)); - } else if (!itLockCandidate->second.txLockRequest) { - // i.e. empty Transaction Lock Candidate was created earlier, let's update it with actual data - itLockCandidate->second.txLockRequest = txLockRequest; - if (itLockCandidate->second.IsTimedOut()) { - LogPrintf("CInstantSend::CreateTxLockCandidate -- timed out, txid=%s\n", txHash.ToString()); - return false; - } - LogPrintf("CInstantSend::CreateTxLockCandidate -- update empty, txid=%s\n", txHash.ToString()); - - // all inputs should already be checked by txLockRequest.IsValid() above, just use them now - for (const auto& txin : txLockRequest.tx->vin) { - itLockCandidate->second.AddOutPointLock(txin.prevout); - } - } else { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::CreateTxLockCandidate -- seen, txid=%s\n", txHash.ToString()); - } - - return true; -} - -void CInstantSend::CreateEmptyTxLockCandidate(const uint256& txHash) -{ - if (mapTxLockCandidates.find(txHash) != mapTxLockCandidates.end()) - return; - LogPrintf("CInstantSend::CreateEmptyTxLockCandidate -- new, txid=%s\n", txHash.ToString()); - const CTxLockRequest txLockRequest = CTxLockRequest(); - mapTxLockCandidates.insert(std::make_pair(txHash, CTxLockCandidate(txLockRequest))); -} - -void CInstantSend::Vote(const uint256& txHash, CConnman& connman) -{ - AssertLockHeld(cs_main); -#ifdef ENABLE_WALLET - LOCK(pwalletMain ? &pwalletMain->cs_wallet : NULL); -#endif - - CTxLockRequest dummyRequest; - CTxLockCandidate txLockCandidate(dummyRequest); - { - LOCK(cs_instantsend); - auto itLockCandidate = mapTxLockCandidates.find(txHash); - if (itLockCandidate == mapTxLockCandidates.end()) return; - txLockCandidate = itLockCandidate->second; - Vote(txLockCandidate, connman); - } - - // Let's see if our vote changed smth - LOCK2(mempool.cs, cs_instantsend); - TryToFinalizeLockCandidate(txLockCandidate); -} - -void CInstantSend::Vote(CTxLockCandidate& txLockCandidate, CConnman& connman) -{ - if (!fMasternodeMode) return; - if (!llmq::IsOldInstantSendEnabled()) return; - - AssertLockHeld(cs_main); - AssertLockHeld(cs_instantsend); - - uint256 txHash = txLockCandidate.GetHash(); - // We should never vote on a Transaction Lock Request that was not (yet) accepted by the mempool - if (mapLockRequestAccepted.find(txHash) == mapLockRequestAccepted.end()) return; - // check if we need to vote on this candidate's outpoints, - // it's possible that we need to vote for several of them - for (auto& outpointLockPair : txLockCandidate.mapOutPointLocks) { - int nPrevoutHeight = GetUTXOHeight(outpointLockPair.first); - if (nPrevoutHeight == -1) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::Vote -- Failed to find UTXO %s\n", outpointLockPair.first.ToStringShort()); - return; - } - - int nLockInputHeight = nPrevoutHeight + Params().GetConsensus().nInstantSendConfirmationsRequired - 2; - - int nRank; - uint256 quorumModifierHash; - if (!CMasternodeUtils::GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, quorumModifierHash, nLockInputHeight)) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternodeInfo.outpoint.ToStringShort()); - continue; - } - - int nSignaturesTotal = Params().GetConsensus().nInstantSendSigsTotal; - if (nRank > nSignaturesTotal) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, nRank); - continue; - } - - LogPrint(BCLog::INSTANTSEND, "CInstantSend::Vote -- In the top %d (%d)\n", nSignaturesTotal, nRank); - - std::map >::iterator itVoted = mapVotedOutpoints.find(outpointLockPair.first); - - // Check to see if we already voted for this outpoint, - // refuse to vote twice or to include the same outpoint in another tx - bool fAlreadyVoted = false; - if (itVoted != mapVotedOutpoints.end()) { - for (const auto& hash : itVoted->second) { - std::map::iterator it2 = mapTxLockCandidates.find(hash); - if (it2->second.HasMasternodeVoted(outpointLockPair.first, activeMasternodeInfo.outpoint)) { - // we already voted for this outpoint to be included either in the same tx or in a competing one, - // skip it anyway - fAlreadyVoted = true; - LogPrintf("CInstantSend::Vote -- WARNING: We already voted for this outpoint, skipping: txHash=%s, outpoint=%s\n", - txHash.ToString(), outpointLockPair.first.ToStringShort()); - break; - } - } - } - if (fAlreadyVoted) { - continue; // skip to the next outpoint - } - - // we haven't voted for this outpoint yet, let's try to do this now - // Please note that activeMasternodeInfo.proTxHash is only valid after spork15 activation - CTxLockVote vote(txHash, outpointLockPair.first, activeMasternodeInfo.outpoint, quorumModifierHash, activeMasternodeInfo.proTxHash); - - if (!vote.Sign()) { - LogPrintf("CInstantSend::Vote -- Failed to sign consensus vote\n"); - return; - } - if (!vote.CheckSignature()) { - LogPrintf("CInstantSend::Vote -- Signature invalid\n"); - return; - } - - // vote constructed sucessfully, let's store and relay it - uint256 nVoteHash = vote.GetHash(); - mapTxLockVotes.insert(std::make_pair(nVoteHash, vote)); - if (outpointLockPair.second.AddVote(vote)) { - LogPrintf("CInstantSend::Vote -- Vote created successfully, relaying: txHash=%s, outpoint=%s, vote=%s\n", - txHash.ToString(), outpointLockPair.first.ToStringShort(), nVoteHash.ToString()); - - if (itVoted == mapVotedOutpoints.end()) { - std::set setHashes; - setHashes.insert(txHash); - mapVotedOutpoints.insert(std::make_pair(outpointLockPair.first, setHashes)); - } else { - mapVotedOutpoints[outpointLockPair.first].insert(txHash); - if (mapVotedOutpoints[outpointLockPair.first].size() > 1) { - // it's ok to continue, just warn user - LogPrintf("CInstantSend::Vote -- WARNING: Vote conflicts with some existing votes: txHash=%s, outpoint=%s, vote=%s\n", - txHash.ToString(), outpointLockPair.first.ToStringShort(), nVoteHash.ToString()); - } - } - - vote.Relay(connman); - } - } -} - -bool CInstantSend::ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, CConnman& connman) -{ - uint256 txHash = vote.GetTxHash(); - uint256 nVoteHash = vote.GetHash(); - - if (!vote.IsValid(pfrom, connman)) { - // could be because of missing MN - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Vote is invalid, txid=%s\n", __func__, txHash.ToString()); - return false; - } - - // relay valid vote asap - vote.Relay(connman); - - LOCK(cs_main); -#ifdef ENABLE_WALLET - LOCK(pwalletMain ? &pwalletMain->cs_wallet : NULL); -#endif - LOCK2(mempool.cs, cs_instantsend); - - // Masternodes will sometimes propagate votes before the transaction is known to the client, - // will actually process only after the lock request itself has arrived - - std::map::iterator it = mapTxLockCandidates.find(txHash); - if (it == mapTxLockCandidates.end() || !it->second.txLockRequest) { - // no or empty tx lock candidate - if (it == mapTxLockCandidates.end()) { - // start timeout countdown after the very first vote - CreateEmptyTxLockCandidate(txHash); - } - bool fInserted = mapTxLockVotesOrphan.emplace(nVoteHash, vote).second; - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Orphan vote: txid=%s masternode=%s %s\n", - __func__, txHash.ToString(), vote.GetMasternodeOutpoint().ToStringShort(), fInserted ? "new" : "seen"); - - // This tracks those messages and allows only the same rate as of the rest of the network - // TODO: make sure this works good enough for multi-quorum - - int nMasternodeOrphanExpireTime = GetTime() + 60*10; // keep time data for 10 minutes - auto itMnOV = mapMasternodeOrphanVotes.find(vote.GetMasternodeOutpoint()); - if (itMnOV == mapMasternodeOrphanVotes.end()) { - mapMasternodeOrphanVotes.emplace(vote.GetMasternodeOutpoint(), nMasternodeOrphanExpireTime); - } else { - if (itMnOV->second > GetTime() && itMnOV->second > GetAverageMasternodeOrphanVoteTime()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- masternode is spamming orphan Transaction Lock Votes: txid=%s masternode=%s\n", - __func__, txHash.ToString(), vote.GetMasternodeOutpoint().ToStringShort()); - // Misbehaving(pfrom->GetId(), 1); - return false; - } - // not spamming, refresh - itMnOV->second = nMasternodeOrphanExpireTime; - } - - return true; - } - - // We have a valid (non-empty) tx lock candidate - CTxLockCandidate& txLockCandidate = it->second; - - if (txLockCandidate.IsTimedOut()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- too late, Transaction Lock timed out, txid=%s\n", __func__, txHash.ToString()); - return false; - } - - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Transaction Lock Vote, txid=%s\n", __func__, txHash.ToString()); - - UpdateVotedOutpoints(vote, txLockCandidate); - - if (!txLockCandidate.AddVote(vote)) { - // this should never happen - return false; - } - - int nSignatures = txLockCandidate.CountVotes(); - int nSignaturesMax = txLockCandidate.txLockRequest.GetMaxSignatures(); - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Transaction Lock signatures count: %d/%d, vote hash=%s\n", __func__, - nSignatures, nSignaturesMax, nVoteHash.ToString()); - - TryToFinalizeLockCandidate(txLockCandidate); - - return true; -} - -bool CInstantSend::ProcessOrphanTxLockVote(const CTxLockVote& vote) -{ - // cs_main, cs_wallet and cs_instantsend should be already locked - AssertLockHeld(cs_main); -#ifdef ENABLE_WALLET - if (pwalletMain) - AssertLockHeld(pwalletMain->cs_wallet); -#endif - AssertLockHeld(cs_instantsend); - - uint256 txHash = vote.GetTxHash(); - - // We shouldn't process orphan votes without a valid tx lock candidate - std::map::iterator it = mapTxLockCandidates.find(txHash); - if (it == mapTxLockCandidates.end() || !it->second.txLockRequest) - return false; // this shouldn never happen - - CTxLockCandidate& txLockCandidate = it->second; - - if (txLockCandidate.IsTimedOut()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- too late, Transaction Lock timed out, txid=%s\n", __func__, txHash.ToString()); - return false; - } - - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Transaction Lock Vote, txid=%s\n", __func__, txHash.ToString()); - - UpdateVotedOutpoints(vote, txLockCandidate); - - if (!txLockCandidate.AddVote(vote)) { - // this should never happen - return false; - } - - int nSignatures = txLockCandidate.CountVotes(); - int nSignaturesMax = txLockCandidate.txLockRequest.GetMaxSignatures(); - LogPrint(BCLog::INSTANTSEND, "CInstantSend::%s -- Transaction Lock signatures count: %d/%d, vote hash=%s\n", - __func__, nSignatures, nSignaturesMax, vote.GetHash().ToString()); - - return true; -} - -void CInstantSend::UpdateVotedOutpoints(const CTxLockVote& vote, CTxLockCandidate& txLockCandidate) -{ - AssertLockHeld(cs_instantsend); - - uint256 txHash = vote.GetTxHash(); - - std::map >::iterator it1 = mapVotedOutpoints.find(vote.GetOutpoint()); - if (it1 != mapVotedOutpoints.end()) { - for (const auto& hash : it1->second) { - if (hash != txHash) { - // same outpoint was already voted to be locked by another tx lock request, - // let's see if it was the same masternode who voted on this outpoint - // for another tx lock request - std::map::iterator it2 = mapTxLockCandidates.find(hash); - if (it2 !=mapTxLockCandidates.end() && it2->second.HasMasternodeVoted(vote.GetOutpoint(), vote.GetMasternodeOutpoint())) { - // yes, it was the same masternode - LogPrintf("CInstantSend::%s -- masternode sent conflicting votes! %s\n", __func__, vote.GetMasternodeOutpoint().ToStringShort()); - // mark both Lock Candidates as attacked, none of them should complete, - // or at least the new (current) one shouldn't even - // if the second one was already completed earlier - txLockCandidate.MarkOutpointAsAttacked(vote.GetOutpoint()); - it2->second.MarkOutpointAsAttacked(vote.GetOutpoint()); - // apply maximum PoSe ban score to this masternode i.e. PoSe-ban it instantly - // 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. - } - } - } - // store all votes, regardless of them being sent by malicious masternode or not - it1->second.insert(txHash); - } else { - mapVotedOutpoints.emplace(vote.GetOutpoint(), std::set({txHash})); - } -} - -void CInstantSend::ProcessOrphanTxLockVotes() -{ - AssertLockHeld(cs_main); - AssertLockHeld(cs_instantsend); - - std::map::iterator it = mapTxLockVotesOrphan.begin(); - while (it != mapTxLockVotesOrphan.end()) { - if (ProcessOrphanTxLockVote(it->second)) { - mapTxLockVotesOrphan.erase(it++); - } else { - ++it; - } - } -} - -void CInstantSend::TryToFinalizeLockCandidate(const CTxLockCandidate& txLockCandidate) -{ - if (!llmq::IsOldInstantSendEnabled()) return; - - AssertLockHeld(cs_main); - AssertLockHeld(cs_instantsend); - - uint256 txHash = txLockCandidate.txLockRequest.tx->GetHash(); - if (txLockCandidate.IsAllOutPointsReady() && !IsLockedInstantSendTransaction(txHash)) { - // we have enough votes now - LogPrint(BCLog::INSTANTSEND, "CInstantSend::TryToFinalizeLockCandidate -- Transaction Lock is ready to complete, txid=%s\n", txHash.ToString()); - if (ResolveConflicts(txLockCandidate)) { - LockTransactionInputs(txLockCandidate); - UpdateLockedTransaction(txLockCandidate); - } - } -} - -void CInstantSend::UpdateLockedTransaction(const CTxLockCandidate& txLockCandidate) -{ - // cs_main, cs_wallet and cs_instantsend should be already locked - AssertLockHeld(cs_main); -#ifdef ENABLE_WALLET - if (pwalletMain) { - AssertLockHeld(pwalletMain->cs_wallet); - } -#endif - AssertLockHeld(cs_instantsend); - - uint256 txHash = txLockCandidate.GetHash(); - - if (!IsLockedInstantSendTransaction(txHash)) return; // not a locked tx, do not update/notify - - llmq::CInstantSendLock islock; - GetMainSignals().NotifyTransactionLock(*txLockCandidate.txLockRequest.tx, islock); - - LogPrint(BCLog::INSTANTSEND, "CInstantSend::UpdateLockedTransaction -- done, txid=%s\n", txHash.ToString()); -} - -void CInstantSend::LockTransactionInputs(const CTxLockCandidate& txLockCandidate) -{ - if (!llmq::IsOldInstantSendEnabled()) return; - - LOCK(cs_instantsend); - - uint256 txHash = txLockCandidate.GetHash(); - - if (!txLockCandidate.IsAllOutPointsReady()) return; - - for (const auto& pair : txLockCandidate.mapOutPointLocks) { - mapLockedOutpoints.insert(std::make_pair(pair.first, txHash)); - } - LogPrint(BCLog::INSTANTSEND, "CInstantSend::LockTransactionInputs -- done, txid=%s\n", txHash.ToString()); -} - -bool CInstantSend::GetLockedOutPointTxHash(const COutPoint& outpoint, uint256& hashRet) -{ - LOCK(cs_instantsend); - std::map::iterator it = mapLockedOutpoints.find(outpoint); - if (it == mapLockedOutpoints.end()) return false; - hashRet = it->second; - return true; -} - -bool CInstantSend::ResolveConflicts(const CTxLockCandidate& txLockCandidate) -{ - AssertLockHeld(cs_main); - AssertLockHeld(cs_instantsend); - - uint256 txHash = txLockCandidate.GetHash(); - - // make sure the lock is ready - if (!txLockCandidate.IsAllOutPointsReady()) return false; - - AssertLockHeld(mempool.cs); // protect mempool.mapNextTx - - for (const auto& txin : txLockCandidate.txLockRequest.tx->vin) { - uint256 hashConflicting; - if (GetLockedOutPointTxHash(txin.prevout, hashConflicting) && txHash != hashConflicting) { - // completed lock which conflicts with another completed one? - // this means that majority of MNs in the quorum for this specific tx input are malicious! - std::map::iterator itLockCandidate = mapTxLockCandidates.find(txHash); - std::map::iterator itLockCandidateConflicting = mapTxLockCandidates.find(hashConflicting); - if (itLockCandidate == mapTxLockCandidates.end() || itLockCandidateConflicting == mapTxLockCandidates.end()) { - // safety check, should never really happen - LogPrintf("CInstantSend::ResolveConflicts -- ERROR: Found conflicting completed Transaction Lock, but one of txLockCandidate-s is missing, txid=%s, conflicting txid=%s\n", - txHash.ToString(), hashConflicting.ToString()); - return false; - } - LogPrintf("CInstantSend::ResolveConflicts -- WARNING: Found conflicting completed Transaction Lock, dropping both, txid=%s, conflicting txid=%s\n", - txHash.ToString(), hashConflicting.ToString()); - CTxLockRequest txLockRequest = itLockCandidate->second.txLockRequest; - CTxLockRequest txLockRequestConflicting = itLockCandidateConflicting->second.txLockRequest; - itLockCandidate->second.SetConfirmedHeight(0); // expired - itLockCandidateConflicting->second.SetConfirmedHeight(0); // expired - CheckAndRemove(); // clean up - // AlreadyHave should still return "true" for both of them - mapLockRequestRejected.insert(std::make_pair(txHash, txLockRequest)); - mapLockRequestRejected.insert(std::make_pair(hashConflicting, txLockRequestConflicting)); - - // TODO: clean up mapLockRequestRejected later somehow - // (not a big issue since we already PoSe ban malicious masternodes - // and they won't be able to spam) - // TODO: ban all malicious masternodes permanently, do not accept anything from them, ever - - // TODO: notify zmq+script about this double-spend attempt - // and let merchant cancel/hold the order if it's not too late... - - // can't do anything else, fallback to regular txes - return false; - } else if (mempool.mapNextTx.count(txin.prevout)) { - // check if it's in mempool - hashConflicting = mempool.mapNextTx.find(txin.prevout)->second->GetHash(); - if (txHash == hashConflicting) continue; // matches current, not a conflict, skip to next txin - // conflicts with tx in mempool - LogPrintf("CInstantSend::ResolveConflicts -- ERROR: Failed to complete Transaction Lock, conflicts with mempool, txid=%s\n", txHash.ToString()); - return false; - } - } // FOREACH - // No conflicts were found so far, check to see if it was already included in block - CTransactionRef txTmp; - uint256 hashBlock; - if (GetTransaction(txHash, txTmp, Params().GetConsensus(), hashBlock, true) && hashBlock != uint256()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::ResolveConflicts -- Done, %s is included in block %s\n", txHash.ToString(), hashBlock.ToString()); - return true; - } - // Not in block yet, make sure all its inputs are still unspent - for (const auto& txin : txLockCandidate.txLockRequest.tx->vin) { - Coin coin; - if (!GetUTXOCoin(txin.prevout, coin)) { - // Not in UTXO anymore? A conflicting tx was mined while we were waiting for votes. - LogPrintf("CInstantSend::ResolveConflicts -- ERROR: Failed to find UTXO %s, can't complete Transaction Lock\n", txin.prevout.ToStringShort()); - return false; - } - } - LogPrint(BCLog::INSTANTSEND, "CInstantSend::ResolveConflicts -- Done, txid=%s\n", txHash.ToString()); - - return true; -} - -int64_t CInstantSend::GetAverageMasternodeOrphanVoteTime() -{ - LOCK(cs_instantsend); - // NOTE: should never actually call this function when mapMasternodeOrphanVotes is empty - if (mapMasternodeOrphanVotes.empty()) return 0; - - int64_t total = 0; - for (const auto& pair : mapMasternodeOrphanVotes) { - total += pair.second; - } - - return total / mapMasternodeOrphanVotes.size(); -} - -void CInstantSend::CheckAndRemove() -{ - if (!masternodeSync.IsBlockchainSynced()) return; - - LOCK(cs_instantsend); - - std::map::iterator itLockCandidate = mapTxLockCandidates.begin(); - - // remove expired candidates - while (itLockCandidate != mapTxLockCandidates.end()) { - CTxLockCandidate &txLockCandidate = itLockCandidate->second; - uint256 txHash = txLockCandidate.GetHash(); - if (txLockCandidate.IsExpired(nCachedBlockHeight)) { - LogPrintf("CInstantSend::CheckAndRemove -- Removing expired Transaction Lock Candidate: txid=%s\n", txHash.ToString()); - - for (const auto& pair : txLockCandidate.mapOutPointLocks) { - mapLockedOutpoints.erase(pair.first); - mapVotedOutpoints.erase(pair.first); - } - mapLockRequestAccepted.erase(txHash); - mapLockRequestRejected.erase(txHash); - mapTxLockCandidates.erase(itLockCandidate++); - } else { - ++itLockCandidate; - } - } - - // remove expired votes - std::map::iterator itVote = mapTxLockVotes.begin(); - while (itVote != mapTxLockVotes.end()) { - if (itVote->second.IsExpired(nCachedBlockHeight)) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::CheckAndRemove -- Removing expired vote: txid=%s masternode=%s\n", - itVote->second.GetTxHash().ToString(), itVote->second.GetMasternodeOutpoint().ToStringShort()); - mapTxLockVotes.erase(itVote++); - } else { - ++itVote; - } - } - - // remove timed out orphan votes - std::map::iterator itOrphanVote = mapTxLockVotesOrphan.begin(); - while (itOrphanVote != mapTxLockVotesOrphan.end()) { - if (itOrphanVote->second.IsTimedOut()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::CheckAndRemove -- Removing timed out orphan vote: txid=%s masternode=%s\n", - itOrphanVote->second.GetTxHash().ToString(), itOrphanVote->second.GetMasternodeOutpoint().ToStringShort()); - mapTxLockVotes.erase(itOrphanVote->first); - mapTxLockVotesOrphan.erase(itOrphanVote++); - } else { - ++itOrphanVote; - } - } - - // remove invalid votes and votes for failed lock attempts - itVote = mapTxLockVotes.begin(); - while (itVote != mapTxLockVotes.end()) { - if (itVote->second.IsFailed()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::CheckAndRemove -- Removing vote for failed lock attempt: txid=%s masternode=%s\n", - itVote->second.GetTxHash().ToString(), itVote->second.GetMasternodeOutpoint().ToStringShort()); - mapTxLockVotes.erase(itVote++); - } else { - ++itVote; - } - } - - // remove timed out masternode orphan votes (DOS protection) - std::map::iterator itMasternodeOrphan = mapMasternodeOrphanVotes.begin(); - while (itMasternodeOrphan != mapMasternodeOrphanVotes.end()) { - if (itMasternodeOrphan->second < GetTime()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::CheckAndRemove -- Removing timed out orphan masternode vote: masternode=%s\n", - itMasternodeOrphan->first.ToStringShort()); - mapMasternodeOrphanVotes.erase(itMasternodeOrphan++); - } else { - ++itMasternodeOrphan; - } - } - LogPrintf("CInstantSend::CheckAndRemove -- %s\n", ToString()); -} - -bool CInstantSend::AlreadyHave(const uint256& hash) -{ - if (!llmq::IsOldInstantSendEnabled()) { - return true; - } - - LOCK(cs_instantsend); - return mapLockRequestAccepted.count(hash) || - mapLockRequestRejected.count(hash) || - mapTxLockVotes.count(hash); -} - -void CInstantSend::AcceptLockRequest(const CTxLockRequest& txLockRequest) -{ - LOCK(cs_instantsend); - mapLockRequestAccepted.insert(std::make_pair(txLockRequest.GetHash(), txLockRequest)); -} - -void CInstantSend::RejectLockRequest(const CTxLockRequest& txLockRequest) -{ - LOCK(cs_instantsend); - mapLockRequestRejected.insert(std::make_pair(txLockRequest.GetHash(), txLockRequest)); -} - -bool CInstantSend::HasTxLockRequest(const uint256& txHash) -{ - CTxLockRequest txLockRequestTmp; - return GetTxLockRequest(txHash, txLockRequestTmp); -} - -bool CInstantSend::GetTxLockRequest(const uint256& txHash, CTxLockRequest& txLockRequestRet) -{ - if (!llmq::IsOldInstantSendEnabled()) { - return false; - } - - LOCK(cs_instantsend); - - std::map::iterator it = mapTxLockCandidates.find(txHash); - if (it == mapTxLockCandidates.end() || !it->second.txLockRequest) return false; - txLockRequestRet = it->second.txLockRequest; - - return true; -} - -bool CInstantSend::GetTxLockVote(const uint256& hash, CTxLockVote& txLockVoteRet) -{ - if (!llmq::IsOldInstantSendEnabled()) { - return false; - } - - LOCK(cs_instantsend); - - std::map::iterator it = mapTxLockVotes.find(hash); - if (it == mapTxLockVotes.end()) return false; - txLockVoteRet = it->second; - - return true; -} - -void CInstantSend::Clear() -{ - LOCK(cs_instantsend); - - mapLockRequestAccepted.clear(); - mapLockRequestRejected.clear(); - mapTxLockVotes.clear(); - mapTxLockVotesOrphan.clear(); - mapTxLockCandidates.clear(); - mapVotedOutpoints.clear(); - mapLockedOutpoints.clear(); - mapMasternodeOrphanVotes.clear(); - nCachedBlockHeight = 0; -} - -bool CInstantSend::IsLockedInstantSendTransaction(const uint256& txHash) -{ - if (!fEnableInstantSend || GetfLargeWorkForkFound() || GetfLargeWorkInvalidChainFound() || - !sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) return false; - - LOCK(cs_instantsend); - - // there must be a lock candidate - std::map::iterator itLockCandidate = mapTxLockCandidates.find(txHash); - if (itLockCandidate == mapTxLockCandidates.end()) return false; - - // which should have outpoints - if (itLockCandidate->second.mapOutPointLocks.empty()) return false; - - // and all of these outputs must be included in mapLockedOutpoints with correct hash - for (const auto& pair : itLockCandidate->second.mapOutPointLocks) { - uint256 hashLocked; - if (!GetLockedOutPointTxHash(pair.first, hashLocked) || hashLocked != txHash) return false; - } - - return true; -} - -int CInstantSend::GetTransactionLockSignatures(const uint256& txHash) -{ - if (!fEnableInstantSend) return -1; - if (GetfLargeWorkForkFound() || GetfLargeWorkInvalidChainFound()) return -2; - if (!llmq::IsOldInstantSendEnabled()) return -3; - - LOCK(cs_instantsend); - - std::map::iterator itLockCandidate = mapTxLockCandidates.find(txHash); - if (itLockCandidate != mapTxLockCandidates.end()) { - return itLockCandidate->second.CountVotes(); - } - - return -1; -} - -bool CInstantSend::IsTxLockCandidateTimedOut(const uint256& txHash) -{ - if (!fEnableInstantSend) return false; - - LOCK(cs_instantsend); - - std::map::iterator itLockCandidate = mapTxLockCandidates.find(txHash); - if (itLockCandidate != mapTxLockCandidates.end()) { - return !itLockCandidate->second.IsAllOutPointsReady() && - itLockCandidate->second.IsTimedOut(); - } - - return false; -} - -void CInstantSend::Relay(const uint256& txHash, CConnman& connman) -{ - LOCK(cs_instantsend); - - std::map::const_iterator itLockCandidate = mapTxLockCandidates.find(txHash); - if (itLockCandidate != mapTxLockCandidates.end()) { - itLockCandidate->second.Relay(connman); - } -} - -void CInstantSend::UpdatedBlockTip(const CBlockIndex *pindex) -{ - nCachedBlockHeight = pindex->nHeight; -} - -void CInstantSend::SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex, int posInBlock) -{ - // Update lock candidates and votes if corresponding tx confirmed - // or went from confirmed to 0-confirmed or conflicted. - - if (tx->IsCoinBase()) return; - - LOCK2(cs_main, cs_instantsend); - - uint256 txHash = tx->GetHash(); - - // When tx is 0-confirmed or conflicted, posInBlock is -1 and nHeightNew should be set to -1 - int nHeightNew = (posInBlock == -1 || pindex == nullptr) ? -1 : pindex->nHeight; - - LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d\n", txHash.ToString(), nHeightNew); - - // Check lock candidates - std::map::iterator itLockCandidate = mapTxLockCandidates.find(txHash); - if (itLockCandidate != mapTxLockCandidates.end()) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d lock candidate updated\n", - txHash.ToString(), nHeightNew); - itLockCandidate->second.SetConfirmedHeight(nHeightNew); - // Loop through outpoint locks - for (const auto& pair : itLockCandidate->second.mapOutPointLocks) { - // Check corresponding lock votes - for (const auto& vote : pair.second.GetVotes()) { - uint256 nVoteHash = vote.GetHash(); - LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d vote %s updated\n", - txHash.ToString(), nHeightNew, nVoteHash.ToString()); - const auto& it = mapTxLockVotes.find(nVoteHash); - if (it != mapTxLockVotes.end()) { - it->second.SetConfirmedHeight(nHeightNew); - } - } - } - } - - // check orphan votes - for (const auto& pair : mapTxLockVotesOrphan) { - if (pair.second.GetTxHash() == txHash) { - LogPrint(BCLog::INSTANTSEND, "CInstantSend::SyncTransaction -- txid=%s nHeightNew=%d vote %s updated\n", - txHash.ToString(), nHeightNew, pair.first.ToString()); - mapTxLockVotes[pair.first].SetConfirmedHeight(nHeightNew); - } - } -} - -std::string CInstantSend::ToString() const -{ - LOCK(cs_instantsend); - return strprintf("Lock Candidates: %llu, Votes %llu", mapTxLockCandidates.size(), mapTxLockVotes.size()); -} - -void CInstantSend::DoMaintenance() -{ - if (ShutdownRequested()) return; - - CheckAndRemove(); -} - -bool CInstantSend::CanAutoLock() -{ - if (!isAutoLockBip9Active || !llmq::IsOldInstantSendEnabled()) { - return false; - } - if (!sporkManager.IsSporkActive(SPORK_16_INSTANTSEND_AUTOLOCKS)) { - return false; - } - return (mempool.UsedMemoryShare() < AUTO_IX_MEMPOOL_THRESHOLD); -} - -// -// CTxLockRequest -// - -bool CTxLockRequest::IsValid() const -{ - if (tx->vout.size() < 1) return false; - - if (tx->vin.size() > WARN_MANY_INPUTS) { - LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- WARNING: Too many inputs: tx=%s", ToString()); - } - - AssertLockHeld(cs_main); - if (!CheckFinalTx(*tx)) { - LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- Transaction is not final: tx=%s", ToString()); - return false; - } - - CAmount nValueIn = 0; - - int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired; - - for (const auto& txin : tx->vin) { - - Coin coin; - - if (!GetUTXOCoin(txin.prevout, coin)) { - LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- Failed to find UTXO %s\n", txin.prevout.ToStringShort()); - return false; - } - - int nTxAge = chainActive.Height() - coin.nHeight + 1; - // 1 less than the "send IX" gui requires, in case of a block propagating the network at the time - int nConfirmationsRequired = nInstantSendConfirmationsRequired - 1; - - if (nTxAge < nConfirmationsRequired) { - LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- outpoint %s too new: nTxAge=%d, nConfirmationsRequired=%d, txid=%s\n", - txin.prevout.ToStringShort(), nTxAge, nConfirmationsRequired, GetHash().ToString()); - return false; - } - - nValueIn += coin.out.nValue; - } - - if (nValueIn > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) { - LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- Transaction value too high: nValueIn=%d, tx=%s", nValueIn, ToString()); - return false; - } - - CAmount nValueOut = tx->GetValueOut(); - - if (nValueIn - nValueOut < GetMinFee(false)) { - LogPrint(BCLog::INSTANTSEND, "CTxLockRequest::IsValid -- did not include enough fees in transaction: fees=%d, tx=%s", nValueOut - nValueIn, ToString()); - return false; - } - - return true; -} - -CAmount CTxLockRequest::GetMinFee(bool fForceMinFee) const -{ - if (!fForceMinFee && CInstantSend::CanAutoLock() && IsSimple()) { - return CAmount(); - } - CAmount nMinFee = MIN_FEE; - return std::max(nMinFee, CAmount(tx->vin.size() * nMinFee)); -} - -int CTxLockRequest::GetMaxSignatures() const -{ - return tx->vin.size() * Params().GetConsensus().nInstantSendSigsTotal; -} - -bool CTxLockRequest::IsSimple() const -{ - return (tx->vin.size() <= MAX_INPUTS_FOR_AUTO_IX); -} - -// -// CTxLockVote -// - -bool CTxLockVote::IsValid(CNode* pnode, CConnman& connman) const -{ - auto mnList = deterministicMNManager->GetListAtChainTip(); - - if (!mnList.HasValidMNByCollateral(outpointMasternode)) { - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Unknown masternode %s\n", outpointMasternode.ToStringShort()); - return false; - } - - // Verify that masternodeProTxHash belongs to the same MN referred by the collateral - // 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()) { - auto dmn = mnList.GetValidMN(masternodeProTxHash); - if (!dmn || dmn->collateralOutpoint != outpointMasternode) { - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- invalid masternodeProTxHash %s\n", masternodeProTxHash.ToString()); - return false; - } - } else { - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- missing masternodeProTxHash\n"); - return false; - } - - Coin coin; - if (!GetUTXOCoin(outpoint, coin)) { - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Failed to find UTXO %s\n", outpoint.ToStringShort()); - return false; - } - - int nLockInputHeight = coin.nHeight + Params().GetConsensus().nInstantSendConfirmationsRequired - 2; - - int nRank; - uint256 expectedQuorumModifierHash; - if (!CMasternodeUtils::GetMasternodeRank(outpointMasternode, nRank, expectedQuorumModifierHash, nLockInputHeight)) { - //can be caused by past versions trying to vote with an invalid protocol - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Can't calculate rank for masternode %s\n", outpointMasternode.ToStringShort()); - return false; - } - if (!quorumModifierHash.IsNull()) { - if (quorumModifierHash != expectedQuorumModifierHash) { - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- invalid quorumModifierHash %s, expected %s\n", quorumModifierHash.ToString(), expectedQuorumModifierHash.ToString()); - return false; - } - } else { - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- missing quorumModifierHash\n"); - return false; - } - - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Masternode %s, rank=%d\n", outpointMasternode.ToStringShort(), nRank); - - int nSignaturesTotal = Params().GetConsensus().nInstantSendSigsTotal; - if (nRank > nSignaturesTotal) { - LogPrint(BCLog::INSTANTSEND, "CTxLockVote::IsValid -- Masternode %s is not in the top %d (%d), vote hash=%s\n", - outpointMasternode.ToStringShort(), nSignaturesTotal, nRank, GetHash().ToString()); - return false; - } - - if (!CheckSignature()) { - LogPrintf("CTxLockVote::IsValid -- Signature invalid\n"); - return false; - } - - return true; -} - -uint256 CTxLockVote::GetHash() const -{ - return SerializeHash(*this); -} - -uint256 CTxLockVote::GetSignatureHash() const -{ - return GetHash(); -} - -bool CTxLockVote::CheckSignature() const -{ - std::string strError; - - auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(masternodeProTxHash); - if (!dmn) { - LogPrintf("CTxLockVote::CheckSignature -- Unknown Masternode: masternode=%s\n", masternodeProTxHash.ToString()); - return false; - } - - uint256 hash = GetSignatureHash(); - - CBLSSignature sig; - sig.SetBuf(vchMasternodeSignature); - if (!sig.IsValid() || !sig.VerifyInsecure(dmn->pdmnState->pubKeyOperator.Get(), hash)) { - LogPrintf("CTxLockVote::CheckSignature -- VerifyInsecure() failed\n"); - return false; - } - return true; -} - -bool CTxLockVote::Sign() -{ - - uint256 hash = GetSignatureHash(); - - CBLSSignature sig = activeMasternodeInfo.blsKeyOperator->Sign(hash); - if (!sig.IsValid()) { - return false; - } - sig.GetBuf(vchMasternodeSignature); - return true; -} - -void CTxLockVote::Relay(CConnman& connman) const -{ - CInv inv(MSG_TXLOCK_VOTE, GetHash()); - CTxLockRequest request; - if (instantsend.GetTxLockRequest(txHash, request) && request) { - connman.RelayInvFiltered(inv, *request.tx); - } else { - connman.RelayInvFiltered(inv, txHash); - } -} - -bool CTxLockVote::IsExpired(int nHeight) const -{ - // Locks and votes expire nInstantSendKeepLock blocks after the block corresponding tx was included into. - return (nConfirmedHeight != -1) && (nHeight - nConfirmedHeight > Params().GetConsensus().nInstantSendKeepLock); -} - -bool CTxLockVote::IsTimedOut() const -{ - return GetTime() - nTimeCreated > INSTANTSEND_LOCK_TIMEOUT_SECONDS; -} - -bool CTxLockVote::IsFailed() const -{ - return (GetTime() - nTimeCreated > INSTANTSEND_FAILED_TIMEOUT_SECONDS) && !instantsend.IsLockedInstantSendTransaction(GetTxHash()); -} - -// -// COutPointLock -// - -bool COutPointLock::AddVote(const CTxLockVote& vote) -{ - return mapMasternodeVotes.emplace(vote.GetMasternodeOutpoint(), vote).second; -} - -std::vector COutPointLock::GetVotes() const -{ - std::vector vRet; - for (const auto& pair : mapMasternodeVotes) { - vRet.push_back(pair.second); - } - return vRet; -} - -bool COutPointLock::HasMasternodeVoted(const COutPoint& outpointMasternodeIn) const -{ - return mapMasternodeVotes.count(outpointMasternodeIn); -} - -bool COutPointLock::IsReady() const -{ - return !fAttacked && CountVotes() >= Params().GetConsensus().nInstantSendSigsRequired; -} - -void COutPointLock::Relay(CConnman& connman) const -{ - for (const auto& pair : mapMasternodeVotes) { - pair.second.Relay(connman); - } -} - -// -// CTxLockCandidate -// - -void CTxLockCandidate::AddOutPointLock(const COutPoint& outpoint) -{ - mapOutPointLocks.insert(std::make_pair(outpoint, COutPointLock(outpoint))); -} - -void CTxLockCandidate::MarkOutpointAsAttacked(const COutPoint& outpoint) -{ - std::map::iterator it = mapOutPointLocks.find(outpoint); - if (it != mapOutPointLocks.end()) - it->second.MarkAsAttacked(); -} - -bool CTxLockCandidate::AddVote(const CTxLockVote& vote) -{ - std::map::iterator it = mapOutPointLocks.find(vote.GetOutpoint()); - if (it == mapOutPointLocks.end()) return false; - return it->second.AddVote(vote); -} - -bool CTxLockCandidate::IsAllOutPointsReady() const -{ - if (mapOutPointLocks.empty()) return false; - - for (const auto& pair : mapOutPointLocks) { - if (!pair.second.IsReady()) return false; - } - return true; -} - -bool CTxLockCandidate::HasMasternodeVoted(const COutPoint& outpointIn, const COutPoint& outpointMasternodeIn) -{ - std::map::iterator it = mapOutPointLocks.find(outpointIn); - return it !=mapOutPointLocks.end() && it->second.HasMasternodeVoted(outpointMasternodeIn); -} - -int CTxLockCandidate::CountVotes() const -{ - // Note: do NOT use vote count to figure out if tx is locked, use IsAllOutPointsReady() instead - int nCountVotes = 0; - for (const auto& pair : mapOutPointLocks) { - nCountVotes += pair.second.CountVotes(); - } - return nCountVotes; -} - -bool CTxLockCandidate::IsExpired(int nHeight) const -{ - // Locks and votes expire nInstantSendKeepLock blocks after the block corresponding tx was included into. - return (nConfirmedHeight != -1) && (nHeight - nConfirmedHeight > Params().GetConsensus().nInstantSendKeepLock); -} - -bool CTxLockCandidate::IsTimedOut() const -{ - return GetTime() - nTimeCreated > INSTANTSEND_LOCK_TIMEOUT_SECONDS; -} - -void CTxLockCandidate::Relay(CConnman& connman) const -{ - connman.RelayTransaction(*txLockRequest.tx); - for (const auto& pair : mapOutPointLocks) { - pair.second.Relay(connman); - } -} diff --git a/src/instantsend.h b/src/instantsend.h deleted file mode 100644 index 49006ce4e243..000000000000 --- a/src/instantsend.h +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright (c) 2014-2019 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 INSTANTX_H -#define INSTANTX_H - -#include "chain.h" -#include "net.h" -#include "primitives/transaction.h" - -#include "evo/deterministicmns.h" - -class CTxLockVote; -class COutPointLock; -class CTxLockRequest; -class CTxLockCandidate; -class CInstantSend; - -extern CInstantSend instantsend; - -/* - At 15 signatures, 1/2 of the masternode network can be owned by - one party without compromising the security of InstantSend - (1000/2150.0)**10 = 0.00047382219560689856 - (1000/2900.0)**10 = 2.3769498616783657e-05 - - ### getting 5 of 10 signatures w/ 1000 nodes of 2900 - (1000/2900.0)**5 = 0.004875397277841433 -*/ - -static const int MIN_INSTANTSEND_PROTO_VERSION = 70213; - -/// For how long we are going to accept votes/locks -/// after we saw the first one for a specific transaction -static const int INSTANTSEND_LOCK_TIMEOUT_SECONDS = 15; -/// For how long we are going to keep invalid votes and votes for failed lock attempts, -/// must be greater than INSTANTSEND_LOCK_TIMEOUT_SECONDS -static const int INSTANTSEND_FAILED_TIMEOUT_SECONDS = 60; - -extern bool fEnableInstantSend; - -/** - * Manages InstantSend. Processes lock requests, candidates, and votes. - */ -class CInstantSend -{ -public: - /// Automatic locks of "simple" transactions are only allowed - /// when mempool usage is lower than this threshold - static const double AUTO_IX_MEMPOOL_THRESHOLD; -private: - static const std::string SERIALIZATION_VERSION_STRING; - - // Keep track of current block height - int nCachedBlockHeight; - - // maps for AlreadyHave - std::map mapLockRequestAccepted; ///< Tx hash - Tx - std::map mapLockRequestRejected; ///< Tx hash - Tx - std::map mapTxLockVotes; ///< Vote hash - Vote - std::map mapTxLockVotesOrphan; ///< Vote hash - Vote - - std::map mapTxLockCandidates; ///< Tx hash - Lock candidate - - std::map > mapVotedOutpoints; ///< UTXO - Tx hash set - std::map mapLockedOutpoints; ///< UTXO - Tx hash - - /// Track masternodes who voted with no txlockrequest (for DOS protection) - std::map mapMasternodeOrphanVotes; ///< MN outpoint - Time - - bool CreateTxLockCandidate(const CTxLockRequest& txLockRequest); - void CreateEmptyTxLockCandidate(const uint256& txHash); - void Vote(CTxLockCandidate& txLockCandidate, CConnman& connman); - - /// Process consensus vote message - bool ProcessNewTxLockVote(CNode* pfrom, const CTxLockVote& vote, CConnman& connman); - - void UpdateVotedOutpoints(const CTxLockVote& vote, CTxLockCandidate& txLockCandidate); - bool ProcessOrphanTxLockVote(const CTxLockVote& vote); - void ProcessOrphanTxLockVotes(); - int64_t GetAverageMasternodeOrphanVoteTime(); - - void TryToFinalizeLockCandidate(const CTxLockCandidate& txLockCandidate); - void LockTransactionInputs(const CTxLockCandidate& txLockCandidate); - /// Update UI and notify external script if any - void UpdateLockedTransaction(const CTxLockCandidate& txLockCandidate); - bool ResolveConflicts(const CTxLockCandidate& txLockCandidate); - -public: - mutable CCriticalSection cs_instantsend; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - std::string strVersion; - if(ser_action.ForRead()) { - READWRITE(strVersion); - } - else { - strVersion = SERIALIZATION_VERSION_STRING; - READWRITE(strVersion); - } - - READWRITE(mapLockRequestAccepted); - READWRITE(mapLockRequestRejected); - READWRITE(mapTxLockVotes); - READWRITE(mapTxLockVotesOrphan); - READWRITE(mapTxLockCandidates); - READWRITE(mapVotedOutpoints); - READWRITE(mapLockedOutpoints); - READWRITE(mapMasternodeOrphanVotes); - READWRITE(nCachedBlockHeight); - - if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) { - Clear(); - } - } - - void Clear(); - - void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman); - - bool ProcessTxLockRequest(const CTxLockRequest& txLockRequest, CConnman& connman); - void Vote(const uint256& txHash, CConnman& connman); - - bool AlreadyHave(const uint256& hash); - - void AcceptLockRequest(const CTxLockRequest& txLockRequest); - void RejectLockRequest(const CTxLockRequest& txLockRequest); - bool HasTxLockRequest(const uint256& txHash); - bool GetTxLockRequest(const uint256& txHash, CTxLockRequest& txLockRequestRet); - - bool GetTxLockVote(const uint256& hash, CTxLockVote& txLockVoteRet); - - bool GetLockedOutPointTxHash(const COutPoint& outpoint, uint256& hashRet); - - /// Verify if transaction is currently locked - bool IsLockedInstantSendTransaction(const uint256& txHash); - /// Get the actual number of accepted lock signatures - int GetTransactionLockSignatures(const uint256& txHash); - - /// Remove expired entries from maps - void CheckAndRemove(); - /// Verify if transaction lock timed out - bool IsTxLockCandidateTimedOut(const uint256& txHash); - - void Relay(const uint256& txHash, CConnman& connman); - - void UpdatedBlockTip(const CBlockIndex *pindex); - void SyncTransaction(const CTransactionRef& tx, const CBlockIndex* pindex = nullptr, int posInBlock = 0); - - std::string ToString() const; - - void DoMaintenance(); - - /// checks if we can automatically lock "simple" transactions - static bool CanAutoLock(); - - /// flag of the AutoLock Bip9 activation - static std::atomic isAutoLockBip9Active; -}; - -/** - * An InstantSend transaction lock request. - */ -class CTxLockRequest -{ -private: - static const CAmount MIN_FEE = 0.0001 * COIN; - /// If transaction has less or equal inputs than MAX_INPUTS_FOR_AUTO_IX, - /// it will be automatically locked - static const int MAX_INPUTS_FOR_AUTO_IX = 4; - -public: - /// Warn for a large number of inputs to an IS tx - fees could be substantial - /// and the number txlvote responses requested large (10 * # of inputs) - static const int WARN_MANY_INPUTS = 100; - - CTransactionRef tx; - - CTxLockRequest() : tx(MakeTransactionRef()) {} - CTxLockRequest(const CTransaction& _tx) : tx(MakeTransactionRef(_tx)) {}; - CTxLockRequest(const CTransactionRef& _tx) : tx(_tx) {}; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(tx); - } - - bool IsValid() const; - CAmount GetMinFee(bool fForceMinFee) const; - int GetMaxSignatures() const; - - // checks if related transaction is "simple" to lock it automatically - bool IsSimple() const; - - const uint256 &GetHash() const { - return tx->GetHash(); - } - - std::string ToString() const { - return tx->ToString(); - } - - friend bool operator==(const CTxLockRequest& a, const CTxLockRequest& b) - { - return *a.tx == *b.tx; - } - - friend bool operator!=(const CTxLockRequest& a, const CTxLockRequest& b) - { - return *a.tx != *b.tx; - } - - explicit operator bool() const - { - return *this != CTxLockRequest(); - } -}; - -/** - * An InstantSend transaction lock vote. Sent by a masternode in response to a - * transaction lock request (ix message) to indicate the transaction input can - * be locked. Contains the proposed transaction's hash and the outpoint being - * locked along with the masternodes outpoint and signature. - * @see CTxLockRequest - */ -class CTxLockVote -{ -private: - uint256 txHash; - COutPoint outpoint; - // TODO remove this member (not needed anymore after DIP3 has been deployed) - COutPoint outpointMasternode; - uint256 quorumModifierHash; - uint256 masternodeProTxHash; - std::vector vchMasternodeSignature; - // local memory only - int nConfirmedHeight; ///< When corresponding tx is 0-confirmed or conflicted, nConfirmedHeight is -1 - int64_t nTimeCreated; - -public: - CTxLockVote() : - txHash(), - outpoint(), - outpointMasternode(), - quorumModifierHash(), - masternodeProTxHash(), - vchMasternodeSignature(), - nConfirmedHeight(-1), - nTimeCreated(GetTime()) - {} - - CTxLockVote(const uint256& txHashIn, const COutPoint& outpointIn, const COutPoint& outpointMasternodeIn, const uint256& quorumModifierHashIn, const uint256& masternodeProTxHashIn) : - txHash(txHashIn), - outpoint(outpointIn), - outpointMasternode(outpointMasternodeIn), - quorumModifierHash(quorumModifierHashIn), - masternodeProTxHash(masternodeProTxHashIn), - vchMasternodeSignature(), - nConfirmedHeight(-1), - nTimeCreated(GetTime()) - {} - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(txHash); - READWRITE(outpoint); - READWRITE(outpointMasternode); - READWRITE(quorumModifierHash); - READWRITE(masternodeProTxHash); - if (!(s.GetType() & SER_GETHASH)) { - READWRITE(vchMasternodeSignature); - } - } - - uint256 GetHash() const; - uint256 GetSignatureHash() const; - - uint256 GetTxHash() const { return txHash; } - COutPoint GetOutpoint() const { return outpoint; } - COutPoint GetMasternodeOutpoint() const { return outpointMasternode; } - - bool IsValid(CNode* pnode, CConnman& connman) const; - void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; } - bool IsExpired(int nHeight) const; - bool IsTimedOut() const; - bool IsFailed() const; - - bool Sign(); - bool CheckSignature() const; - - void Relay(CConnman& connman) const; -}; - -/** - * An InstantSend OutpointLock. - */ -class COutPointLock -{ -private: - COutPoint outpoint; ///< UTXO - std::map mapMasternodeVotes; ///< Masternode outpoint - vote - bool fAttacked = false; - -public: - COutPointLock() {} - - COutPointLock(const COutPoint& outpointIn) : - outpoint(outpointIn), - mapMasternodeVotes() - {} - - COutPoint GetOutpoint() const { return outpoint; } - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(outpoint); - READWRITE(mapMasternodeVotes); - READWRITE(fAttacked); - } - - bool AddVote(const CTxLockVote& vote); - std::vector GetVotes() const; - bool HasMasternodeVoted(const COutPoint& outpointMasternodeIn) const; - int CountVotes() const { return fAttacked ? 0 : mapMasternodeVotes.size(); } - bool IsReady() const; - void MarkAsAttacked() { fAttacked = true; } - - void Relay(CConnman& connman) const; -}; - -/** - * An InstantSend transaction lock candidate. - */ -class CTxLockCandidate -{ -private: - int nConfirmedHeight; /// mapOutPointLocks; - - ADD_SERIALIZE_METHODS; - - template - inline void SerializationOp(Stream& s, Operation ser_action) { - READWRITE(txLockRequest); - READWRITE(mapOutPointLocks); - READWRITE(nTimeCreated); - READWRITE(nConfirmedHeight); - } - - uint256 GetHash() const { return txLockRequest.GetHash(); } - - void AddOutPointLock(const COutPoint& outpoint); - void MarkOutpointAsAttacked(const COutPoint& outpoint); - bool AddVote(const CTxLockVote& vote); - bool IsAllOutPointsReady() const; - - bool HasMasternodeVoted(const COutPoint& outpointIn, const COutPoint& outpointMasternodeIn); - int CountVotes() const; - - void SetConfirmedHeight(int nConfirmedHeightIn) { nConfirmedHeight = nConfirmedHeightIn; } - bool IsExpired(int nHeight) const; - bool IsTimedOut() const; - - void Relay(CConnman& connman) const; -}; - -#endif diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 5a8a37b9a1e1..bbb106d37a2b 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -286,7 +286,7 @@ void CChainLocksHandler::TrySignChainTip() // considered safe when it is ixlocked or at least known since 10 minutes (from mempool or block). These checks are // performed for the tip (which we try to sign) and the previous 5 blocks. If a ChainLocked block is found on the // way down, we consider all TXs to be safe. - if (IsNewInstantSendEnabled() && sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) { + if (IsInstantSendEnabled() && sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) { auto pindexWalk = pindex; while (pindexWalk) { if (pindex->nHeight - pindexWalk->nHeight > 5) { @@ -453,7 +453,7 @@ bool CChainLocksHandler::IsTxSafeForMining(const uint256& txid) if (!sporkManager.IsSporkActive(SPORK_3_INSTANTSEND_BLOCK_FILTERING)) { return true; } - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return true; } diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index 3b20bcd0fd6e..6aee659c11c7 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -19,9 +19,6 @@ #include "wallet/wallet.h" #endif -// needed for AUTO_IX_MEMPOOL_THRESHOLD -#include "instantsend.h" - #include #include @@ -383,7 +380,7 @@ void CInstantSendManager::InterruptWorkerThread() bool CInstantSendManager::ProcessTx(const CTransaction& tx, const Consensus::Params& params) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return true; } @@ -466,10 +463,6 @@ bool CInstantSendManager::ProcessTx(const CTransaction& tx, const Consensus::Par bool CInstantSendManager::CheckCanLock(const CTransaction& tx, bool printDebug, const Consensus::Params& params) { - if (sporkManager.IsSporkActive(SPORK_16_INSTANTSEND_AUTOLOCKS) && (mempool.UsedMemoryShare() > CInstantSend::AUTO_IX_MEMPOOL_THRESHOLD)) { - return false; - } - if (tx.vin.empty()) { // can't lock TXs without inputs (e.g. quorum commitments) return false; @@ -485,18 +478,6 @@ bool CInstantSendManager::CheckCanLock(const CTransaction& tx, bool printDebug, nValueIn += v; } - // TODO decide if we should limit max input values. This was ok to do in the old system, but in the new system - // where we want to have all TXs locked at some point, this is counterproductive (especially when ChainLocks later - // depend on all TXs being locked first) -// CAmount maxValueIn = sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE); -// if (nValueIn > maxValueIn * COIN) { -// if (printDebug) { -// LogPrint(BCLog::INSTANTSEND, "CInstantSendManager::%s -- txid=%s: TX input value too high. nValueIn=%f, maxValueIn=%d", __func__, -// tx.GetHash().ToString(), nValueIn / (double)COIN, maxValueIn); -// } -// return false; -// } - return true; } @@ -556,7 +537,7 @@ bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebu void CInstantSendManager::HandleNewRecoveredSig(const CRecoveredSig& recoveredSig) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return; } @@ -674,7 +655,7 @@ void CInstantSendManager::HandleNewInstantSendLockRecoveredSig(const llmq::CReco void CInstantSendManager::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return; } @@ -747,7 +728,7 @@ bool CInstantSendManager::ProcessPendingInstantSendLocks() return false; } - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return false; } @@ -936,7 +917,7 @@ void CInstantSendManager::UpdateWalletTransaction(const CTransactionRef& tx, con void CInstantSendManager::ProcessNewTransaction(const CTransactionRef& tx, const CBlockIndex* pindex) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return; } @@ -985,7 +966,7 @@ void CInstantSendManager::TransactionAddedToMempool(const CTransactionRef& tx) void CInstantSendManager::BlockConnected(const std::shared_ptr& pblock, const CBlockIndex* pindex, const std::vector& vtxConflicted) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return; } @@ -1323,7 +1304,7 @@ bool CInstantSendManager::ProcessPendingRetryLockTxs() return false; } - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return false; } @@ -1380,7 +1361,7 @@ bool CInstantSendManager::ProcessPendingRetryLockTxs() bool CInstantSendManager::AlreadyHave(const CInv& inv) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return true; } @@ -1390,7 +1371,7 @@ bool CInstantSendManager::AlreadyHave(const CInv& inv) bool CInstantSendManager::GetInstantSendLockByHash(const uint256& hash, llmq::CInstantSendLock& ret) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return false; } @@ -1405,7 +1386,7 @@ bool CInstantSendManager::GetInstantSendLockByHash(const uint256& hash, llmq::CI bool CInstantSendManager::IsLocked(const uint256& txHash) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return false; } @@ -1420,7 +1401,7 @@ bool CInstantSendManager::IsConflicted(const CTransaction& tx) CInstantSendLockPtr CInstantSendManager::GetConflictingLock(const CTransaction& tx) { - if (!IsNewInstantSendEnabled()) { + if (!IsInstantSendEnabled()) { return nullptr; } @@ -1459,16 +1440,6 @@ void CInstantSendManager::WorkThreadMain() } } -bool IsOldInstantSendEnabled() -{ - return sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED) && !sporkManager.IsSporkActive(SPORK_20_INSTANTSEND_LLMQ_BASED); -} - -bool IsNewInstantSendEnabled() -{ - return sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED) && sporkManager.IsSporkActive(SPORK_20_INSTANTSEND_LLMQ_BASED); -} - bool IsInstantSendEnabled() { return sporkManager.IsSporkActive(SPORK_2_INSTANTSEND_ENABLED); diff --git a/src/llmq/quorums_instantsend.h b/src/llmq/quorums_instantsend.h index 4ba1e3a678bc..0be4e47b6c1e 100644 --- a/src/llmq/quorums_instantsend.h +++ b/src/llmq/quorums_instantsend.h @@ -170,13 +170,6 @@ class CInstantSendManager : public CRecoveredSigsListener extern CInstantSendManager* quorumInstantSendManager; -// This involves 2 sporks: SPORK_2_INSTANTSEND_ENABLED and SPORK_20_INSTANTSEND_LLMQ_BASED -// SPORK_2_INSTANTSEND_ENABLED generally enables/disables InstantSend and SPORK_20_INSTANTSEND_LLMQ_BASED switches -// between the old and the new (LLMQ based) system -// TODO When the new system is fully deployed and enabled, we can remove this special handling in a future version -// and revert to only using SPORK_2_INSTANTSEND_ENABLED. -bool IsOldInstantSendEnabled(); -bool IsNewInstantSendEnabled(); bool IsInstantSendEnabled(); } diff --git a/src/net.cpp b/src/net.cpp index 7a09e5467284..8a8e94a17f99 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -25,10 +25,9 @@ #include "utilstrencodings.h" #include "validation.h" -#include "instantsend.h" #include "masternode/masternode-sync.h" #include "privatesend/privatesend.h" -#include "llmq/quorums_instantsend.h" +#include "evo/deterministicmns.h" #ifdef WIN32 #include @@ -2892,21 +2891,11 @@ void CConnman::RelayTransaction(const CTransaction& tx) int nInv = MSG_TX; if (CPrivateSend::GetDSTX(hash)) { nInv = MSG_DSTX; - } else if (llmq::IsOldInstantSendEnabled() && instantsend.HasTxLockRequest(hash)) { - nInv = MSG_TXLOCK_REQUEST; } CInv inv(nInv, hash); LOCK(cs_vNodes); BOOST_FOREACH(CNode* pnode, vNodes) { - if (nInv == MSG_TXLOCK_REQUEST) { - // Additional filtering for lock requests. - // Make it here because lock request processing - // differs from simple tx processing in PushInventory - // and tx info will not be available there. - LOCK(pnode->cs_filter); - if(pnode->pfilter && !pnode->pfilter->IsRelevantAndUpdate(tx)) continue; - } pnode->PushInventory(inv); } } diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 5bd7897033cd..da1c2232c709 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -32,7 +32,6 @@ #include "spork.h" #include "governance/governance.h" -#include "instantsend.h" #include "masternode/masternode-payments.h" #include "masternode/masternode-sync.h" #include "masternode/masternode-meta.h" @@ -954,6 +953,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) switch (inv.type) { case MSG_TX: + case MSG_LEGACY_TXLOCK_REQUEST: // we treat legacy IX messages as TX messages { assert(recentRejects); if (chainActive.Tip()->GetBlockHash() != hashRecentRejectsChainTip) @@ -989,11 +989,6 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) We're going to be asking many nodes upfront for the full inventory list, so we'll get duplicates of these. We want to only update the time on new hits, so that we can time out appropriately if needed. */ - case MSG_TXLOCK_REQUEST: - return instantsend.AlreadyHave(inv.hash); - - case MSG_TXLOCK_VOTE: - return instantsend.AlreadyHave(inv.hash); case MSG_SPORK: { @@ -1215,8 +1210,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam // Send stream from relay memory bool push = false; - // Only serve MSG_TX from mapRelay. - // Otherwise we may send out a normal TX instead of a IX if (inv.type == MSG_TX) { auto mi = mapRelay.find(inv.hash); if (mi != mapRelay.end()) { @@ -1233,22 +1226,6 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam } } - if (!push && inv.type == MSG_TXLOCK_REQUEST) { - CTxLockRequest txLockRequest; - if(instantsend.GetTxLockRequest(inv.hash, txLockRequest)) { - connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::TXLOCKREQUEST, txLockRequest)); - push = true; - } - } - - if (!push && inv.type == MSG_TXLOCK_VOTE) { - CTxLockVote vote; - if(instantsend.GetTxLockVote(inv.hash, vote)) { - connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::TXLOCKVOTE, vote)); - push = true; - } - } - if (!push && inv.type == MSG_SPORK) { CSporkMessage spork; if(sporkManager.GetSporkByHash(inv.hash, spork)) { @@ -2087,7 +2064,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } - else if (strCommand == NetMsgType::TX || strCommand == NetMsgType::DSTX || strCommand == NetMsgType::TXLOCKREQUEST) + else if (strCommand == NetMsgType::TX || strCommand == NetMsgType::DSTX || strCommand == NetMsgType::LEGACYTXLOCKREQUEST) { // Stop processing the transaction early if // We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off @@ -2100,25 +2077,15 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr std::deque vWorkQueue; std::vector vEraseQueue; CTransactionRef ptx; - CTxLockRequest txLockRequest; CPrivateSendBroadcastTx dstx; int nInvType = MSG_TX; - bool fCanAutoLock = false; // Read data and assign inv type if(strCommand == NetMsgType::TX) { vRecv >> ptx; - txLockRequest = CTxLockRequest(ptx); - fCanAutoLock = llmq::IsOldInstantSendEnabled() && CInstantSend::CanAutoLock() && txLockRequest.IsSimple(); - } else if(strCommand == NetMsgType::TXLOCKREQUEST) { - vRecv >> txLockRequest; - ptx = txLockRequest.tx; - nInvType = MSG_TXLOCK_REQUEST; - if (llmq::IsNewInstantSendEnabled()) { - // the new system does not require explicit lock requests - // changing the inv type to MSG_TX also results in re-broadcasting the TX as normal TX - nInvType = MSG_TX; - } + } else if(strCommand == NetMsgType::LEGACYTXLOCKREQUEST) { + // we keep processing the legacy IX message here but revert to handling it as a regular TX + vRecv >> ptx; } else if (strCommand == NetMsgType::DSTX) { vRecv >> dstx; ptx = dstx.tx; @@ -2134,18 +2101,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } // Process custom logic, no matter if tx will be accepted to mempool later or not - if (nInvType == MSG_TXLOCK_REQUEST || fCanAutoLock) { - if(!instantsend.ProcessTxLockRequest(txLockRequest, connman)) { - LogPrint(BCLog::INSTANTSEND, "TXLOCKREQUEST -- failed %s\n", txLockRequest.GetHash().ToString()); - // Should not really happen for "fCanAutoLock == true" but just in case: - if (!fCanAutoLock) { - // Fail only for "true" IS here - return false; - } - // Fallback for normal txes to process as usual - fCanAutoLock = false; - } - } else if (nInvType == MSG_DSTX) { + if (nInvType == MSG_DSTX) { uint256 hashTx = tx.GetHash(); if (!dstx.IsValidStructure()) { LogPrint(BCLog::PRIVATESEND, "DSTX -- Invalid DSTX structure: %s\n", hashTx.ToString()); @@ -2190,11 +2146,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LogPrintf("DSTX -- Masternode transaction accepted, txid=%s, peer=%d\n", tx.GetHash().ToString(), pfrom->GetId()); CPrivateSend::AddDSTX(dstx); - } else if (nInvType == MSG_TXLOCK_REQUEST || fCanAutoLock) { - LogPrintf("TXLOCKREQUEST -- Transaction Lock Request accepted, txid=%s, peer=%d\n", - tx.GetHash().ToString(), pfrom->GetId()); - instantsend.AcceptLockRequest(txLockRequest); - instantsend.Vote(tx.GetHash(), connman); } mempool.check(pcoinsTip); @@ -2306,19 +2257,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } } - if (nInvType == MSG_TXLOCK_REQUEST && !AlreadyHave(inv)) { - // i.e. AcceptToMemoryPool failed, probably because it's conflicting - // with existing normal tx or tx lock for another tx. For the same tx lock - // AlreadyHave would have return "true" already. - - // It's the first time we failed for this tx lock request, - // this should switch AlreadyHave to "true". - instantsend.RejectLockRequest(txLockRequest); - // this lets other nodes to create lock request candidate i.e. - // this allows multiple conflicting lock requests to compete for votes - connman.RelayTransaction(tx); - } - if (pfrom->fWhitelisted && gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) { // Always relay transactions received from whitelisted peers, even // if they were already in the mempool or rejected from it due @@ -3020,7 +2958,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); - instantsend.ProcessMessage(pfrom, strCommand, vRecv, connman); sporkManager.ProcessSpork(pfrom, strCommand, vRecv, connman); masternodeSync.ProcessMessage(pfrom, strCommand, vRecv); governance.ProcessMessage(pfrom, strCommand, vRecv, connman); diff --git a/src/protocol.cpp b/src/protocol.cpp index 3449b54f80ca..0e519a4b6a0b 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -39,8 +39,7 @@ const char *CMPCTBLOCK="cmpctblock"; const char *GETBLOCKTXN="getblocktxn"; const char *BLOCKTXN="blocktxn"; // Dash message types -const char *TXLOCKREQUEST="ix"; -const char *TXLOCKVOTE="txlvote"; +const char *LEGACYTXLOCKREQUEST="ix"; const char *SPORK="spork"; const char *GETSPORKS="getsporks"; const char *DSACCEPT="dsa"; @@ -75,43 +74,6 @@ const char *ISLOCK="islock"; const char *MNAUTH="mnauth"; }; -static const char* ppszTypeName[] = -{ - "ERROR", // Should never occur - NetMsgType::TX, - NetMsgType::BLOCK, - "filtered block", // Should never occur - // Dash message types - // NOTE: include non-implmented here, we must keep this list in sync with enum in protocol.h - NetMsgType::TXLOCKREQUEST, - NetMsgType::TXLOCKVOTE, - NetMsgType::SPORK, - "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, - "unused inv type 19", - "compact block", // Should never occur - NetMsgType::QFCOMMITMENT, - "qdcommit", // was only shortly used on testnet - NetMsgType::QCONTRIB, - NetMsgType::QCOMPLAINT, - NetMsgType::QJUSTIFICATION, - NetMsgType::QPCOMMITMENT, - "qdebugstatus", // was only shortly used on testnet - NetMsgType::QSIGREC, - NetMsgType::CLSIG, - NetMsgType::ISLOCK, -}; - /** All known message types. Keep this in the same order as the list of * messages above and in protocol.h. */ @@ -143,8 +105,7 @@ const static std::string allNetMessageTypes[] = { NetMsgType::BLOCKTXN, // Dash message types // NOTE: do NOT include non-implmented here, we want them to be "Unknown command" in ProcessMessage() - NetMsgType::TXLOCKREQUEST, - NetMsgType::TXLOCKVOTE, + NetMsgType::LEGACYTXLOCKREQUEST, NetMsgType::SPORK, NetMsgType::GETSPORKS, NetMsgType::SENDDSQUEUE, @@ -259,22 +220,6 @@ CInv::CInv() CInv::CInv(int typeIn, const uint256& hashIn) : type(typeIn), hash(hashIn) {} -CInv::CInv(const std::string& strType, const uint256& hashIn) -{ - unsigned int i; - for (i = 1; i < ARRAYLEN(ppszTypeName); i++) - { - if (strType == ppszTypeName[i]) - { - type = i; - break; - } - } - if (i == ARRAYLEN(ppszTypeName)) - throw std::out_of_range(strprintf("CInv::CInv(string, uint256): unknown type '%s'", strType)); - hash = hashIn; -} - bool operator<(const CInv& a, const CInv& b) { return (a.type < b.type || (a.type == b.type && a.hash < b.hash)); @@ -282,22 +227,51 @@ bool operator<(const CInv& a, const CInv& b) bool CInv::IsKnownType() const { - return (type >= 1 && type < (int)ARRAYLEN(ppszTypeName)); + return GetCommandInternal() != nullptr; } -const char* CInv::GetCommand() const +const char* CInv::GetCommandInternal() const { - if (!IsKnownType()) + switch (type) + { + case MSG_TX: return NetMsgType::TX; + case MSG_BLOCK: return NetMsgType::BLOCK; + case MSG_FILTERED_BLOCK: return NetMsgType::MERKLEBLOCK; + case MSG_LEGACY_TXLOCK_REQUEST: return NetMsgType::LEGACYTXLOCKREQUEST; + case MSG_CMPCT_BLOCK: return NetMsgType::CMPCTBLOCK; + case MSG_SPORK: return NetMsgType::SPORK; + case MSG_DSTX: return NetMsgType::DSTX; + case MSG_GOVERNANCE_OBJECT: return NetMsgType::MNGOVERNANCEOBJECT; + case MSG_GOVERNANCE_OBJECT_VOTE: return NetMsgType::MNGOVERNANCEOBJECTVOTE; + case MSG_QUORUM_FINAL_COMMITMENT: return NetMsgType::QFCOMMITMENT; + case MSG_QUORUM_CONTRIB: return NetMsgType::QCONTRIB; + case MSG_QUORUM_COMPLAINT: return NetMsgType::QCOMPLAINT; + case MSG_QUORUM_JUSTIFICATION: return NetMsgType::QJUSTIFICATION; + case MSG_QUORUM_PREMATURE_COMMITMENT: return NetMsgType::QPCOMMITMENT; + case MSG_QUORUM_RECOVERED_SIG: return NetMsgType::QSIGREC; + case MSG_CLSIG: return NetMsgType::CLSIG; + case MSG_ISLOCK: return NetMsgType::ISLOCK; + default: + return nullptr; + } +} + +std::string CInv::GetCommand() const +{ + auto cmd = GetCommandInternal(); + if (cmd == nullptr) { throw std::out_of_range(strprintf("CInv::GetCommand(): type=%d unknown type", type)); - return ppszTypeName[type]; + } + return cmd; } std::string CInv::ToString() const { - try { - return strprintf("%s %s", GetCommand(), hash.ToString()); - } catch(const std::out_of_range &) { + auto cmd = GetCommandInternal(); + if (!cmd) { return strprintf("0x%08x %s", type, hash.ToString()); + } else { + return strprintf("%s %s", cmd, hash.ToString()); } } diff --git a/src/protocol.h b/src/protocol.h index bce6790c662a..9f363fe058a2 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -239,8 +239,7 @@ extern const char *BLOCKTXN; // Dash message types // NOTE: do NOT declare non-implmented here, we don't want them to be exposed to the outside // TODO: add description -extern const char *TXLOCKREQUEST; -extern const char *TXLOCKVOTE; +extern const char *LEGACYTXLOCKREQUEST; // only present for backwards compatibility extern const char *SPORK; extern const char *GETSPORKS; extern const char *DSACCEPT; @@ -355,8 +354,8 @@ enum GetDataMsg { MSG_FILTERED_BLOCK = 3, //!< Defined in BIP37 // Dash message types // NOTE: declare non-implmented here, we must keep this enum consistent and backwards compatible - MSG_TXLOCK_REQUEST = 4, - MSG_TXLOCK_VOTE = 5, + MSG_LEGACY_TXLOCK_REQUEST = 4, + /* MSG_TXLOCK_VOTE = 5, Legacy InstantSend and not used anymore */ MSG_SPORK = 6, /* 7 - 15 were used in old Dash versions and were mainly budget and MN broadcast/ping related*/ MSG_DSTX = 16, @@ -384,7 +383,6 @@ class CInv public: CInv(); CInv(int typeIn, const uint256& hashIn); - CInv(const std::string& strType, const uint256& hashIn); ADD_SERIALIZE_METHODS; @@ -398,9 +396,12 @@ class CInv friend bool operator<(const CInv& a, const CInv& b); bool IsKnownType() const; - const char* GetCommand() const; + std::string GetCommand() const; std::string ToString() const; +private: + const char* GetCommandInternal() const; + // TODO: make private (improves encapsulation) public: int type; diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index ab8ee15376fc..f6c47e025fdc 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -21,7 +21,6 @@ #include "validation.h" // For mempool #include "wallet/wallet.h" -#include "instantsend.h" #include "privatesend/privatesend-client.h" #include @@ -536,10 +535,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytesInputs += 148; // in all error cases, simply assume 148 here } else nBytesInputs += 148; - - // Add inputs to calculate InstantSend Fee later - if(coinControl->fUseInstantSend) - txDummy.vin.push_back(CTxIn()); } // calculation @@ -556,9 +551,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) // Fee nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, ::mempool, ::feeEstimator); - // InstantSend Fee - if (coinControl->fUseInstantSend) nPayFee = std::max(nPayFee, CTxLockRequest(txDummy).GetMinFee(true)); - if (nPayAmount > 0) { nChange = nAmount - nPayAmount; diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui index 83909a0596d6..cc19bb21259c 100644 --- a/src/qt/forms/receivecoinsdialog.ui +++ b/src/qt/forms/receivecoinsdialog.ui @@ -127,7 +127,7 @@ - + @@ -176,23 +176,13 @@ - + - - - - Request InstantSend - - - true - - - diff --git a/src/qt/forms/sendcoinsdialog.ui b/src/qt/forms/sendcoinsdialog.ui index 45953e7a22f0..25101354441c 100644 --- a/src/qt/forms/sendcoinsdialog.ui +++ b/src/qt/forms/sendcoinsdialog.ui @@ -1278,22 +1278,6 @@ - - - - true - - - - 85 - 0 - - - - InstantSend - - - diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index 9fca533cf17b..5a75c7ea0c25 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -165,7 +165,6 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) QList > items = uriQuery.queryItems(); #endif - rv.fUseInstantSend = false; for (QList >::iterator i = items.begin(); i != items.end(); i++) { bool fShouldReturnFalse = false; @@ -182,9 +181,7 @@ bool parseBitcoinURI(const QUrl &uri, SendCoinsRecipient *out) } if (i->first == "IS") { - if(i->second.compare(QString("1")) == 0) - rv.fUseInstantSend = true; - + // we simply ignore IS fShouldReturnFalse = false; } if (i->first == "message") @@ -253,12 +250,6 @@ QString formatBitcoinURI(const SendCoinsRecipient &info) paramCount++; } - if(info.fUseInstantSend) - { - ret += QString("%1IS=1").arg(paramCount == 0 ? "?" : "&"); - paramCount++; - } - return ret; } diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 9cbe884601dc..95c70218fb3e 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -18,7 +18,6 @@ #include "utilitydialog.h" #include "walletmodel.h" -#include "instantsend.h" #include "masternode/masternode-sync.h" #include "privatesend/privatesend-client.h" diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 1d087aec74c8..11a105cb5661 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -157,7 +157,6 @@ void ReceiveCoinsDialog::on_receiveButton_clicked() } SendCoinsRecipient info(address, label, ui->reqAmount->value(), ui->reqMessage->text()); - info.fUseInstantSend = ui->checkUseInstantSend->isChecked(); ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setModel(model->getOptionsModel()); diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp index 25461f1bab43..b9fcc0198fdd 100644 --- a/src/qt/receiverequestdialog.cpp +++ b/src/qt/receiverequestdialog.cpp @@ -149,7 +149,6 @@ void ReceiveRequestDialog::update() html += ""+tr("Label")+": " + GUIUtil::HtmlEscape(info.label) + "
"; if(!info.message.isEmpty()) html += ""+tr("Message")+": " + GUIUtil::HtmlEscape(info.message) + "
"; - html += ""+tr("InstantSend")+": " + (info.fUseInstantSend ? tr("Yes") : tr("No")) + "
"; ui->outUri->setText(html); #ifdef USE_QRCODE diff --git a/src/qt/res/css/crownium.css b/src/qt/res/css/crownium.css index e05fd4d24e9a..126ea85f794e 100644 --- a/src/qt/res/css/crownium.css +++ b/src/qt/res/css/crownium.css @@ -1288,16 +1288,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 border-radius:5px; padding-top:20px; padding-bottom:18px; -} - -QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */ -color:#555555; -font-weight:bold; -background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0)); -border-radius:5px; -padding-top:20px; -padding-bottom:18px; -margin-left:10px; margin-right:20px; } diff --git a/src/qt/res/css/drkblue.css b/src/qt/res/css/drkblue.css index 7df96e7160b4..1c412fafb12f 100644 --- a/src/qt/res/css/drkblue.css +++ b/src/qt/res/css/drkblue.css @@ -1272,16 +1272,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 border-radius:5px; padding-top:20px; padding-bottom:18px; -} - -QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */ -color:#616161; -font-weight:bold; -background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0)); -border-radius:5px; -padding-top:20px; -padding-bottom:18px; -margin-left:10px; margin-right:20px; } diff --git a/src/qt/res/css/light-hires-retro.css b/src/qt/res/css/light-hires-retro.css index 7e3925bd8722..fa0b157f0075 100644 --- a/src/qt/res/css/light-hires-retro.css +++ b/src/qt/res/css/light-hires-retro.css @@ -1278,16 +1278,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 border-radius:5px; padding-top:20px; padding-bottom:18px; -} - -QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */ -color:#616161; -font-weight:bold; -background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0)); -border-radius:5px; -padding-top:20px; -padding-bottom:18px; -margin-left:10px; margin-right:20px; } diff --git a/src/qt/res/css/light-hires.css b/src/qt/res/css/light-hires.css index c049e3957e2e..253394c88023 100644 --- a/src/qt/res/css/light-hires.css +++ b/src/qt/res/css/light-hires.css @@ -1278,16 +1278,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 border-radius:5px; padding-top:20px; padding-bottom:18px; -} - -QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */ -color:#616161; -font-weight:bold; -background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0)); -border-radius:5px; -padding-top:20px; -padding-bottom:18px; -margin-left:10px; margin-right:20px; } diff --git a/src/qt/res/css/light-retro.css b/src/qt/res/css/light-retro.css index b3b9769aa902..e7bac102f223 100644 --- a/src/qt/res/css/light-retro.css +++ b/src/qt/res/css/light-retro.css @@ -1279,16 +1279,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 border-radius:5px; padding-top:20px; padding-bottom:18px; -} - -QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */ -color:#616161; -font-weight:bold; -background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0)); -border-radius:5px; -padding-top:20px; -padding-bottom:18px; -margin-left:10px; margin-right:20px; } diff --git a/src/qt/res/css/light.css b/src/qt/res/css/light.css index 2b92b8fd0cf3..2d88feb277f7 100644 --- a/src/qt/res/css/light.css +++ b/src/qt/res/css/light.css @@ -1279,16 +1279,6 @@ background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 border-radius:5px; padding-top:20px; padding-bottom:18px; -} - -QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */ -color:#616161; -font-weight:bold; -background: qradialgradient(cx:0.5, cy:0.5, radius: 0.5, fx:0.5, fy:0.5, stop:0 rgba(248, 246, 246, 128), stop: 1 rgba(0, 0, 0, 0)); -border-radius:5px; -padding-top:20px; -padding-bottom:18px; -margin-left:10px; margin-right:20px; } diff --git a/src/qt/res/css/trad.css b/src/qt/res/css/trad.css index 0937a3f007db..52706cb4025e 100644 --- a/src/qt/res/css/trad.css +++ b/src/qt/res/css/trad.css @@ -11,11 +11,6 @@ QWidget#contentWidget { /* The actual content with the text/buttons/etc... */ /* SEND DIALOG */ -QDialog#SendCoinsDialog .QCheckBox#checkUseInstantSend { /* InstantSend Checkbox */ -margin-left:10px; -margin-right:20px; -} - QDialog#SendCoinsDialog QLabel#labelBalance { margin-left:0px; padding-left:0px; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index f4841446a8f7..bc9e57137024 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -82,11 +82,11 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p //TODO remove InstantX sometime after 0.14.1 if (settings.contains("bUseInstantX")) { - settings.setValue("bUseInstantSend", settings.value("bUseInstantX").toBool()); settings.remove("bUseInstantX"); } - if (!settings.contains("bUseInstantSend")) - settings.setValue("bUseInstantSend", false); + if (settings.contains("bUseInstantSend")) { + settings.remove("bUseInstantSend"); + } if (!privateSendClient.fEnablePrivateSend) { ui->checkUsePrivateSend->setChecked(false); @@ -99,17 +99,6 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p connect(ui->checkUsePrivateSend, SIGNAL(stateChanged ( int )), this, SLOT(updateDisplayUnit())); } - if (fLiteMode) { - ui->checkUseInstantSend->setChecked(false); - ui->checkUseInstantSend->setVisible(false); - CoinControlDialog::coinControl->fUseInstantSend = false; - } else{ - bool fUseInstantSend = settings.value("bUseInstantSend").toBool(); - ui->checkUseInstantSend->setChecked(fUseInstantSend); - CoinControlDialog::coinControl->fUseInstantSend = fUseInstantSend; - connect(ui->checkUseInstantSend, SIGNAL(stateChanged ( int )), this, SLOT(updateInstantSend())); - } - // Coin Control: clipboard actions QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this); QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this); @@ -284,14 +273,8 @@ void SendCoinsDialog::on_sendButton_clicked() strFunds = tr("using") + " " + tr("any available funds (not anonymous)") + ""; } - if(model->IsOldInstantSendEnabled() && ui->checkUseInstantSend->isChecked()) { - strFunds += " "; - strFunds += tr("and InstantSend"); - } - for (SendCoinsRecipient& rcp : recipients) { rcp.inputType = ui->checkUsePrivateSend->isChecked() ? ONLY_DENOMINATED : ALL_COINS; - rcp.fUseInstantSend = model->IsOldInstantSendEnabled() && ui->checkUseInstantSend->isChecked(); } fNewRecipientAllowed = false; @@ -622,14 +605,6 @@ void SendCoinsDialog::updateDisplayUnit() updateSmartFeeLabel(); } -void SendCoinsDialog::updateInstantSend() -{ - QSettings settings; - settings.setValue("bUseInstantSend", ui->checkUseInstantSend->isChecked()); - CoinControlDialog::coinControl->fUseInstantSend = model->IsOldInstantSendEnabled() && ui->checkUseInstantSend->isChecked(); - coinControlUpdateLabels(); -} - void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg) { QPair msgParams; diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 4be4a93853c7..ae34d1e6a93b 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -79,7 +79,6 @@ private Q_SLOTS: void on_buttonMinimizeFee_clicked(); void removeEntry(SendCoinsEntry* entry); void updateDisplayUnit(); - void updateInstantSend(); void coinControlFeatureChanged(bool); void coinControlButtonClicked(); void coinControlChangeChecked(int); diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index fd5515124930..1c70a0b81c39 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -64,31 +64,20 @@ void URITests::uriTests() uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?amount=1,000.0&label=Some Example")); QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv)); - uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?amount=100&label=Some Example&message=Some Example Message&IS=1")); + uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?amount=100&label=Some Example&message=Some Example Message")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); QVERIFY(rv.address == QString("XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg")); QVERIFY(rv.amount == 10000000000LL); QVERIFY(rv.label == QString("Some Example")); QVERIFY(rv.message == QString("Some Example Message")); - QVERIFY(rv.fUseInstantSend == 1); - - uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?amount=100&label=Some Example&message=Some Example Message&IS=Something Invalid")); - QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); - QVERIFY(rv.address == QString("XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg")); - QVERIFY(rv.amount == 10000000000LL); - QVERIFY(rv.label == QString("Some Example")); - QVERIFY(rv.message == QString("Some Example Message")); - QVERIFY(rv.fUseInstantSend != 1); + // Verify that IS=xxx does not lead to an error (we ignore the field) uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?IS=1")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); - QVERIFY(rv.fUseInstantSend == 1); - uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?IS=0")); + uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg?req-IS=1")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); - QVERIFY(rv.fUseInstantSend != 1); uri.setUrl(QString("dash:XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg")); QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv)); - QVERIFY(rv.fUseInstantSend != 1); } diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 00ed287ce99f..8a495eddc1a7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -19,8 +19,6 @@ #include "wallet/db.h" #include "wallet/wallet.h" -#include "instantsend.h" - #include #include @@ -57,25 +55,9 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx) } } - if (wtx.IsLockedByLLMQInstantSend()) { + if (wtx.IsLockedByInstantSend()) { strTxStatus += " (" + tr("verified via LLMQ based InstantSend") + ")"; - return strTxStatus; - } - - if(!instantsend.HasTxLockRequest(wtx.GetHash())) return strTxStatus; // regular tx - - int nSignatures = instantsend.GetTransactionLockSignatures(wtx.GetHash()); - int nSignaturesMax = CTxLockRequest(wtx).GetMaxSignatures(); - // InstantSend - strTxStatus += " ("; - if(instantsend.IsLockedInstantSendTransaction(wtx.GetHash())) { - strTxStatus += tr("verified via InstantSend"); - } else if(!instantsend.IsTxLockCandidateTimedOut(wtx.GetHash())) { - strTxStatus += tr("InstantSend verification in progress - %1 of %2 signatures").arg(nSignatures).arg(nSignaturesMax); - } else { - strTxStatus += tr("InstantSend verification failed"); } - strTxStatus += ")"; return strTxStatus; } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 2a8e8fbf16e8..71b3b37b2a3d 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -24,7 +24,6 @@ #include "wallet/wallet.h" #include "wallet/walletdb.h" // for BackupWallet -#include "instantsend.h" #include "spork.h" #include "privatesend/privatesend-client.h" #include "llmq/quorums_instantsend.h" @@ -217,11 +216,6 @@ int WalletModel::getNumISLocks() const return cachedNumISLocks; } -bool WalletModel::IsOldInstantSendEnabled() const -{ - return llmq::IsOldInstantSendEnabled(); -} - void WalletModel::updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status) { @@ -320,12 +314,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact return AmountExceedsBalance; } - if(recipients[0].fUseInstantSend && IsOldInstantSendEnabled() && total > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) { - Q_EMIT message(tr("Send Coins"), tr("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH.").arg(sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)), - CClientUIInterface::MSG_ERROR); - return TransactionCreationFailed; - } - CAmount nFeeRequired = 0; CAmount nValueOut = 0; size_t nVinSize = 0; @@ -341,7 +329,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact CWalletTx* newTx = transaction.getTransaction(); CReserveKey *keyChange = transaction.getPossibleKeyChange(); - fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl, true, recipients[0].inputType, recipients[0].fUseInstantSend); + fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePosRet, strFailReason, coinControl, true, recipients[0].inputType); transaction.setTransactionFee(nFeeRequired); if (fSubtractFeeFromAmount && fCreated) transaction.reassignAmounts(); @@ -350,18 +338,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact nVinSize = newTx->tx->vin.size(); } - if(recipients[0].fUseInstantSend && IsOldInstantSendEnabled()) { - if(nValueOut > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) { - Q_EMIT message(tr("Send Coins"), tr("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH.").arg(sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)), - CClientUIInterface::MSG_ERROR); - return TransactionCreationFailed; - } - if(nVinSize > CTxLockRequest::WARN_MANY_INPUTS) { - Q_EMIT message(tr("Send Coins"), tr("Used way too many inputs (>%1) for this InstantSend transaction, fees could be huge.").arg(CTxLockRequest::WARN_MANY_INPUTS), - CClientUIInterface::MSG_WARNING); - } - } - if(!fCreated) { if(!fSubtractFeeFromAmount && (total + nFeeRequired) > nBalance) @@ -414,12 +390,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran CReserveKey *keyChange = transaction.getPossibleKeyChange(); CValidationState state; - // the new IX system does not require explicit IX messages - std::string strCommand = NetMsgType::TX; - if (recipients[0].fUseInstantSend && IsOldInstantSendEnabled()) { - strCommand = NetMsgType::TXLOCKREQUEST; - } - if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get(), state, strCommand)) + if(!wallet->CommitTransaction(*newTx, *keyChange, g_connman.get(), state)) return SendCoinsReturn(TransactionCommitFailed, QString::fromStdString(state.GetRejectReason())); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 095c94a1d61c..c8fdf4300761 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -54,7 +54,6 @@ class SendCoinsRecipient #ifdef ENABLE_WALLET AvailableCoinsType inputType; #endif // ENABLE_WALLET - bool fUseInstantSend; CAmount amount; // If from a payment request, this is used for storing the memo QString message; @@ -228,8 +227,6 @@ class WalletModel : public QObject int getDefaultConfirmTarget() const; int getNumISLocks() const; - bool IsOldInstantSendEnabled() const; - private: CWallet *wallet; bool fHaveWatchOnly; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index d4aa60021127..7806f425ae3a 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -13,7 +13,6 @@ #include "coins.h" #include "core_io.h" #include "consensus/validation.h" -#include "instantsend.h" #include "validation.h" #include "core_io.h" #include "policy/feerate.h" @@ -368,7 +367,6 @@ std::string EntryDescriptionString() " \"depends\" : [ (array) unconfirmed transactions used as inputs for this transaction\n" " \"transactionid\", (string) parent transaction id\n" " ... ],\n" - " \"instantsend\" : true|false, (boolean) True if this transaction was sent as an InstantSend one\n" " \"instantlock\" : true|false (boolean) True if this transaction was locked via InstantSend\n"; } @@ -402,8 +400,7 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) } info.push_back(Pair("depends", depends)); - info.push_back(Pair("instantsend", instantsend.HasTxLockRequest(tx.GetHash()))); - info.push_back(Pair("instantlock", instantsend.IsLockedInstantSendTransaction(tx.GetHash()) || llmq::quorumInstantSendManager->IsLocked(tx.GetHash()))); + info.push_back(Pair("instantlock", llmq::quorumInstantSendManager->IsLocked(tx.GetHash()))); } UniValue mempoolToJSON(bool fVerbose) diff --git a/src/rpc/governance.cpp b/src/rpc/governance.cpp index 9e3f695bed08..b4e47fb5e5e4 100644 --- a/src/rpc/governance.cpp +++ b/src/rpc/governance.cpp @@ -127,7 +127,7 @@ void gobject_prepare_help(CWallet* const pwallet) "2. revision (numeric, required) object revision in the system\n" "3. time (numeric, required) time this object was created\n" "4. data-hex (string, required) data in hex string form\n" - "5. use-IS (boolean, optional, default=false) InstantSend lock the collateral, only requiring one chain confirmation\n" + "5. use-IS (boolean, optional, default=false) Deprecated and ignored\n" "6. outputHash (string, optional) the single output to submit the proposal fee from\n" "7. outputIndex (numeric, optional) The output index.\n" ); @@ -160,8 +160,6 @@ UniValue gobject_prepare(const JSONRPCRequest& request) int nRevision = atoi(strRevision); int64_t nTime = atoi64(strTime); std::string strDataHex = request.params[4].get_str(); - bool useIS = false; - if (request.params.size() > 5) useIS = request.params[5].getBool(); // CREATE A NEW COLLATERAL TRANSACTION FOR THIS SPECIFIC OBJECT @@ -206,7 +204,7 @@ UniValue gobject_prepare(const JSONRPCRequest& request) } CWalletTx wtx; - if (!pwallet->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), useIS, outpoint)) { + if (!pwallet->GetBudgetSystemCollateralTX(wtx, govobj.GetHash(), govobj.GetMinCollateralFee(), outpoint)) { std::string err = "Error making collateral transaction for governance object. Please check your wallet balance and make sure your wallet is unlocked."; if (request.params.size() == 8) err += "Please verify your specified output is valid and is enough for the combined proposal fee and transaction fee."; throw JSONRPCError(RPC_INTERNAL_ERROR, err); @@ -216,7 +214,7 @@ UniValue gobject_prepare(const JSONRPCRequest& request) CReserveKey reservekey(pwallet); // -- send the tx to the network CValidationState state; - if (!pwallet->CommitTransaction(wtx, reservekey, g_connman.get(), state, NetMsgType::TX)) { + if (!pwallet->CommitTransaction(wtx, reservekey, g_connman.get(), state)) { throw JSONRPCError(RPC_INTERNAL_ERROR, "CommitTransaction failed! Reason given: " + state.GetRejectReason()); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 72c6a8eb0a2d..e5b7d64a06ec 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -24,7 +24,6 @@ #include "txmempool.h" #include "uint256.h" #include "utilstrencodings.h" -#include "instantsend.h" #ifdef ENABLE_WALLET #include "wallet/rpcwallet.h" #include "wallet/wallet.h" @@ -94,10 +93,9 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) } } - bool fLocked = instantsend.IsLockedInstantSendTransaction(txid); - bool fLLMQLocked = llmq::quorumInstantSendManager->IsLocked(txid); - entry.push_back(Pair("instantlock", fLocked || fLLMQLocked || chainLock)); - entry.push_back(Pair("instantlock_internal", fLocked || fLLMQLocked)); + bool fLocked = llmq::quorumInstantSendManager->IsLocked(txid); + entry.push_back(Pair("instantlock", fLocked || chainLock)); + entry.push_back(Pair("instantlock_internal", fLocked)); entry.push_back(Pair("chainlock", chainLock)); } @@ -855,7 +853,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) "\nArguments:\n" "1. \"hexstring\" (string, required) The hex string of the raw transaction)\n" "2. allowhighfees (boolean, optional, default=false) Allow high fees\n" - "3. instantsend (boolean, optional, default=false) Use InstantSend to send this transaction\n" + "3. instantsend (boolean, optional, default=false) Deprecated and ignored\n" "4. bypasslimits (boolean, optional, default=false) Bypass transaction policy limits\n" "\nResult:\n" "\"hex\" (string) The transaction hash in hex\n" @@ -884,10 +882,6 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) if (request.params.size() > 1 && request.params[1].get_bool()) nMaxRawTxFee = 0; - bool fInstantSend = false; - if (request.params.size() > 2) - fInstantSend = request.params[2].get_bool(); - bool fBypassLimits = false; if (request.params.size() > 3) fBypassLimits = request.params[3].get_bool(); @@ -901,9 +895,6 @@ UniValue sendrawtransaction(const JSONRPCRequest& request) bool fHaveMempool = mempool.exists(hashTx); if (!fHaveMempool && !fHaveChain) { // push to local node and sync with wallets - if (fInstantSend && !instantsend.ProcessTxLockRequest(*tx, *g_connman)) { - throw JSONRPCError(RPC_TRANSACTION_ERROR, "Not a valid InstantSend transaction, see debug.log for more info"); - } CValidationState state; bool fMissingInputs; if (!AcceptToMemoryPool(mempool, state, std::move(tx), !fBypassLimits, &fMissingInputs, false, nMaxRawTxFee)) { diff --git a/src/rpc/rpcevo.cpp b/src/rpc/rpcevo.cpp index 35913e245e16..2588be0161a7 100644 --- a/src/rpc/rpcevo.cpp +++ b/src/rpc/rpcevo.cpp @@ -212,7 +212,7 @@ static void FundSpecialTx(CWallet* pwallet, CMutableTransaction& tx, const Speci int nChangePos = -1; std::string strFailReason; - if (!pwallet->CreateTransaction(vecSend, wtx, reservekey, nFee, nChangePos, strFailReason, &coinControl, false, ALL_COINS, false, tx.vExtraPayload.size())) { + if (!pwallet->CreateTransaction(vecSend, wtx, reservekey, nFee, nChangePos, strFailReason, &coinControl, false, ALL_COINS, tx.vExtraPayload.size())) { throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason); } diff --git a/src/spork.cpp b/src/spork.cpp index 953db496c69c..9b4a4d77b840 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -17,9 +17,8 @@ const std::string CSporkManager::SERIALIZATION_VERSION_STRING = "CSporkManager-V #define MAKE_SPORK_DEF(name, defaultValue) CSporkDef{name, defaultValue, #name} std::vector sporkDefs = { - MAKE_SPORK_DEF(SPORK_2_INSTANTSEND_ENABLED, 0), // ON - MAKE_SPORK_DEF(SPORK_3_INSTANTSEND_BLOCK_FILTERING, 0), // ON - MAKE_SPORK_DEF(SPORK_5_INSTANTSEND_MAX_VALUE, 1000), // 1000 Dash + MAKE_SPORK_DEF(SPORK_2_INSTANTSEND_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_3_INSTANTSEND_BLOCK_FILTERING, 4070908800ULL), // OFF MAKE_SPORK_DEF(SPORK_6_NEW_SIGS, 4070908800ULL), // OFF MAKE_SPORK_DEF(SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL), // OFF MAKE_SPORK_DEF(SPORK_15_DETERMINISTIC_MNS_ENABLED, 4070908800ULL), // OFF diff --git a/src/spork.h b/src/spork.h index 1c4efb350688..d2aadcbf654d 100644 --- a/src/spork.h +++ b/src/spork.h @@ -23,7 +23,6 @@ class CSporkManager; enum SporkId : int32_t { SPORK_2_INSTANTSEND_ENABLED = 10001, SPORK_3_INSTANTSEND_BLOCK_FILTERING = 10002, - SPORK_5_INSTANTSEND_MAX_VALUE = 10004, SPORK_6_NEW_SIGS = 10005, SPORK_9_SUPERBLOCKS_ENABLED = 10008, SPORK_15_DETERMINISTIC_MNS_ENABLED = 10014, diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 1836b13529e9..2542091c51d2 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -7,7 +7,6 @@ #include "consensus/consensus.h" #include "consensus/validation.h" -#include "instantsend.h" #include "validation.h" #include "policy/policy.h" #include "policy/fees.h" @@ -1394,16 +1393,6 @@ size_t CTxMemPool::DynamicMemoryUsage() const { return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + memusage::DynamicUsage(mapLinks) + memusage::DynamicUsage(vTxHashes) + cachedInnerUsage; } -double CTxMemPool::UsedMemoryShare() const -{ - // use 1000000 instead of real bytes number in megabyte because of - // this param is calculated in such way in other places (see AppInit - // function in src/init.cpp or mempoolInfoToJSON function in - // src/rpc/blockchain.cpp) - size_t maxmempool = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; - return double(DynamicMemoryUsage()) / maxmempool; -} - void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) { AssertLockHeld(cs); UpdateForRemoveFromMempool(stage, updateDescendants); @@ -1418,7 +1407,7 @@ int CTxMemPool::Expire(int64_t time) { setEntries toremove; while (it != mapTx.get().end() && it->GetTime() < time) { // locked txes do not expire until mined and have sufficient confirmations - if (instantsend.IsLockedInstantSendTransaction(it->GetTx().GetHash()) || llmq::quorumInstantSendManager->IsLocked(it->GetTx().GetHash())) { + if (llmq::quorumInstantSendManager->IsLocked(it->GetTx().GetHash())) { it++; continue; } diff --git a/src/txmempool.h b/src/txmempool.h index bb37c606cd4a..04b6587bd03d 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -672,8 +672,6 @@ class CTxMemPool bool existsProviderTxConflict(const CTransaction &tx) const; size_t DynamicMemoryUsage() const; - // returns share of the used memory to maximum allowed memory - double UsedMemoryShare() const; boost::signals2::signal NotifyEntryAdded; boost::signals2::signal NotifyEntryRemoved; diff --git a/src/validation.cpp b/src/validation.cpp index 5541eb645253..969d242119b6 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -40,7 +40,6 @@ #include "versionbits.h" #include "warnings.h" -#include "instantsend.h" #include "masternode/masternode-payments.h" #include "evo/specialtx.h" @@ -695,21 +694,6 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool if (pool.exists(hash)) return state.Invalid(false, REJECT_ALREADY_KNOWN, "txn-already-in-mempool"); - // If this is a Transaction Lock Request check to see if it's valid - if(instantsend.HasTxLockRequest(hash) && !CTxLockRequest(tx).IsValid()) - return state.DoS(10, error("AcceptToMemoryPool : CTxLockRequest %s is invalid", hash.ToString()), - REJECT_INVALID, "bad-txlockrequest"); - - // Check for conflicts with a completed Transaction Lock - BOOST_FOREACH(const CTxIn &txin, tx.vin) - { - uint256 hashLocked; - if(instantsend.GetLockedOutPointTxHash(txin.prevout, hashLocked) && hash != hashLocked) - return state.DoS(10, error("AcceptToMemoryPool : Transaction %s conflicts with completed Transaction Lock %s", - hash.ToString(), hashLocked.ToString()), - REJECT_INVALID, "tx-txlock-conflict"); - } - llmq::CInstantSendLockPtr conflictLock = llmq::quorumInstantSendManager->GetConflictingLock(tx); if (conflictLock) { CTransactionRef txConflict; @@ -732,18 +716,6 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool { const CTransaction *ptxConflicting = itConflicting->second; - // InstantSend txes are not replacable - if(instantsend.HasTxLockRequest(ptxConflicting->GetHash())) { - // this tx conflicts with a Transaction Lock Request candidate - return state.DoS(0, error("AcceptToMemoryPool : Transaction %s conflicts with Transaction Lock Request %s", - hash.ToString(), ptxConflicting->GetHash().ToString()), - REJECT_INVALID, "tx-txlockreq-mempool-conflict"); - } else if (instantsend.HasTxLockRequest(hash)) { - // this tx is a tx lock request and it conflicts with a normal tx - return state.DoS(0, error("AcceptToMemoryPool : Transaction Lock Request %s conflicts with transaction %s", - hash.ToString(), ptxConflicting->GetHash().ToString()), - REJECT_INVALID, "txlockreq-tx-mempool-conflict"); - } // Transaction conflicts with mempool and RBF doesn't exist in Dash return state.Invalid(false, REJECT_CONFLICT, "txn-mempool-conflict"); } @@ -1807,10 +1779,6 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s } } - // make sure the flag is reset in case of a chain reorg - // (we reused the DIP3 deployment) - instantsend.isAutoLockBip9Active = pindex->nHeight >= Params().GetConsensus().DIP0003Height; - evoDb->WriteBestBlock(pindex->pprev->GetBlockHash()); return fClean ? DISCONNECT_OK : DISCONNECT_UNCLEAN; @@ -2251,17 +2219,6 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd for (const auto& tx : block.vtx) { // skip txes that have no inputs if (tx->vin.empty()) continue; - // LOOK FOR TRANSACTION LOCK IN OUR MAP OF OUTPOINTS - for (const auto& txin : tx->vin) { - uint256 hashLocked; - if (instantsend.GetLockedOutPointTxHash(txin.prevout, hashLocked) && hashLocked != tx->GetHash()) { - // The node which relayed this should switch to correct chain. - // TODO: relay instantsend data/proof. - LOCK(cs_main); - return state.DoS(10, error("ConnectBlock(DASH): transaction %s conflicts with transaction lock %s", tx->GetHash().ToString(), hashLocked.ToString()), - REJECT_INVALID, "conflict-tx-lock"); - } - } llmq::CInstantSendLockPtr conflictLock = llmq::quorumInstantSendManager->GetConflictingLock(*tx); if (!conflictLock) { continue; diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index 2c4c6e710767..1226f0bb80da 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -14,7 +14,6 @@ class CCoinControl public: CTxDestination destChange; bool fUsePrivateSend; - bool fUseInstantSend; //! If false, allows unselected inputs, but requires all selected inputs be used if fAllowOtherInputs is true (default) bool fAllowOtherInputs; //! If false, only include as many inputs as necessary to fulfill a coin selection request. Only usable together with fAllowOtherInputs @@ -40,7 +39,6 @@ class CCoinControl fRequireAllInputs = true; fAllowWatchOnly = false; setSelected.clear(); - fUseInstantSend = false; fUsePrivateSend = true; nFeeRate = CFeeRate(0); fOverrideFeeRate = false; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0adbedcf2529..39a8267c81e0 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -10,7 +10,6 @@ #include "consensus/validation.h" #include "core_io.h" #include "init.h" -#include "instantsend.h" #include "net.h" #include "policy/feerate.h" #include "policy/fees.h" @@ -65,15 +64,14 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) { AssertLockHeld(cs_main); // for mapBlockIndex int confirms = wtx.GetDepthInMainChain(); - bool fLocked = instantsend.IsLockedInstantSendTransaction(wtx.GetHash()); - bool fLLMQLocked = llmq::quorumInstantSendManager->IsLocked(wtx.GetHash()); + bool fLocked = llmq::quorumInstantSendManager->IsLocked(wtx.GetHash()); bool chainlock = false; if (confirms > 0) { chainlock = llmq::chainLocksHandler->HasChainLock(mapBlockIndex[wtx.hashBlock]->nHeight, wtx.hashBlock); } entry.push_back(Pair("confirmations", confirms)); - entry.push_back(Pair("instantlock", fLocked || fLLMQLocked || chainlock)); - entry.push_back(Pair("instantlock_internal", fLocked || fLLMQLocked)); + entry.push_back(Pair("instantlock", fLocked || chainlock)); + entry.push_back(Pair("instantlock_internal", fLocked)); entry.push_back(Pair("chainlock", chainlock)); if (wtx.IsCoinBase()) entry.push_back(Pair("generated", true)); @@ -354,7 +352,7 @@ UniValue getaddressesbyaccount(const JSONRPCRequest& request) return ret; } -static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, bool fUseInstantSend = false, bool fUsePrivateSend = false) +static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew, bool fUsePrivateSend = false) { CAmount curBalance = pwallet->GetBalance(); @@ -381,18 +379,13 @@ static void SendMoney(CWallet * const pwallet, const CTxDestination &address, CA CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount}; vecSend.push_back(recipient); if (!pwallet->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, - strError, NULL, true, fUsePrivateSend ? ONLY_DENOMINATED : ALL_COINS, fUseInstantSend)) { + strError, NULL, true, fUsePrivateSend ? ONLY_DENOMINATED : ALL_COINS)) { if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance) strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired)); throw JSONRPCError(RPC_WALLET_ERROR, strError); } CValidationState state; - // the new IX system does not require explicit IX messages - std::string strCommand = NetMsgType::TX; - if (fUseInstantSend && llmq::IsOldInstantSendEnabled()) { - strCommand = NetMsgType::TXLOCKREQUEST; - } - if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state, strCommand)) { + if (!pwallet->CommitTransaction(wtxNew, reservekey, g_connman.get(), state)) { strError = strprintf("Error: The transaction was rejected! Reason given: %s", state.GetRejectReason()); throw JSONRPCError(RPC_WALLET_ERROR, strError); } @@ -420,7 +413,7 @@ UniValue sendtoaddress(const JSONRPCRequest& request) " transaction, just kept in your wallet.\n" "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n" " The recipient will receive less amount of Dash than you enter in the amount field.\n" - "6. \"use_is\" (bool, optional, default=false) Send this transaction as InstantSend\n" + "6. \"use_is\" (bool, optional, default=false) Deprecated and ignored\n" "7. \"use_ps\" (bool, optional, default=false) Use anonymized funds only\n" "\nResult:\n" "\"txid\" (string) The transaction id.\n" @@ -453,77 +446,25 @@ UniValue sendtoaddress(const JSONRPCRequest& request) if (request.params.size() > 4) fSubtractFeeFromAmount = request.params[4].get_bool(); - bool fUseInstantSend = false; bool fUsePrivateSend = false; - if (request.params.size() > 5) - fUseInstantSend = request.params[5].get_bool(); if (request.params.size() > 6) fUsePrivateSend = request.params[6].get_bool(); EnsureWalletIsUnlocked(pwallet); - SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, fUseInstantSend, fUsePrivateSend); + SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, fUsePrivateSend); return wtx.GetHash().GetHex(); } +// DEPRECATED UniValue instantsendtoaddress(const JSONRPCRequest& request) { - CWallet* const pwallet = GetWalletForJSONRPCRequest(request); - if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) - return NullUniValue; - - if (request.fHelp || request.params.size() < 2 || request.params.size() > 5) - throw std::runtime_error( - "instantsendtoaddress \"address\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n" - "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n" - + HelpRequiringPassphrase(pwallet) + - "\nArguments:\n" - "1. \"address\" (string, required) The dash address to send to.\n" - "2. \"amount\" (numeric, required) The amount in " + CURRENCY_UNIT + " to send. eg 0.1\n" - "3. \"comment\" (string, optional) A comment used to store what the transaction is for. \n" - " This is not part of the transaction, just kept in your wallet.\n" - "4. \"comment_to\" (string, optional) A comment to store the name of the person or organization \n" - " to which you're sending the transaction. This is not part of the \n" - " transaction, just kept in your wallet.\n" - "5. subtractfeefromamount (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n" - " The recipient will receive less amount of Dash than you enter in the amount field.\n" - "\nResult:\n" - "\"transactionid\" (string) The transaction id.\n" - "\nExamples:\n" - + HelpExampleCli("instantsendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1") - + HelpExampleCli("instantsendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1 \"donation\" \"seans outpost\"") - + HelpExampleCli("instantsendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1 \"\" \"\" true") - + HelpExampleRpc("instantsendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", 0.1, \"donation\", \"seans outpost\"") - ); - - LOCK2(cs_main, pwallet->cs_wallet); - - CBitcoinAddress address(request.params[0].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address"); - - // Amount - CAmount nAmount = AmountFromValue(request.params[1]); - if (nAmount <= 0) - throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount for send"); - - // Wallet comments - CWalletTx wtx; - if (request.params.size() > 2 && !request.params[2].isNull() && !request.params[2].get_str().empty()) - wtx.mapValue["comment"] = request.params[2].get_str(); - if (request.params.size() > 3 && !request.params[3].isNull() && !request.params[3].get_str().empty()) - wtx.mapValue["to"] = request.params[3].get_str(); - - bool fSubtractFeeFromAmount = false; - if (request.params.size() > 4) - fSubtractFeeFromAmount = request.params[4].get_bool(); - - EnsureWalletIsUnlocked(pwallet); - - SendMoney(pwallet, address.Get(), nAmount, fSubtractFeeFromAmount, wtx, true); - - return wtx.GetHash().GetHex(); + if (request.fHelp) { + throw std::runtime_error("instantsendtoaddress is deprecated and sendtoaddress should be used instead"); + } + LogPrintf("WARNING: Used deprecated RPC method 'instantsendtoaddress'! Please use 'sendtoaddress' instead\n"); + return sendtoaddress(request); } UniValue listaddressgroupings(const JSONRPCRequest& request) @@ -1022,7 +963,7 @@ UniValue sendmany(const JSONRPCRequest& request) " \"address\" (string) Subtract fee from this address\n" " ,...\n" " ]\n" - "7. \"use_is\" (bool, optional, default=false) Send this transaction as InstantSend\n" + "7. \"use_is\" (bool, optional, default=false) Deprecated and ignored\n" "8. \"use_ps\" (bool, optional, default=false) Use anonymized funds only\n" "\nResult:\n" "\"txid\" (string) The transaction id for the send. Only 1 transaction is created regardless of \n" @@ -1102,24 +1043,16 @@ UniValue sendmany(const JSONRPCRequest& request) CAmount nFeeRequired = 0; int nChangePosRet = -1; std::string strFailReason; - bool fUseInstantSend = false; bool fUsePrivateSend = false; - if (request.params.size() > 6) - fUseInstantSend = request.params[6].get_bool(); if (request.params.size() > 7) fUsePrivateSend = request.params[7].get_bool(); bool fCreated = pwallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason, - NULL, true, fUsePrivateSend ? ONLY_DENOMINATED : ALL_COINS, fUseInstantSend); + NULL, true, fUsePrivateSend ? ONLY_DENOMINATED : ALL_COINS); if (!fCreated) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason); CValidationState state; - // the new IX system does not require explicit IX messages - std::string strCommand = NetMsgType::TX; - if (fUseInstantSend && llmq::IsOldInstantSendEnabled()) { - strCommand = NetMsgType::TXLOCKREQUEST; - } - if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state, strCommand)) { + if (!pwallet->CommitTransaction(wtx, keyChange, g_connman.get(), state)) { strFailReason = strprintf("Transaction commit failed:: %s", state.GetRejectReason()); throw JSONRPCError(RPC_WALLET_ERROR, strFailReason); } @@ -3065,7 +2998,7 @@ static const CRPCCommand commands[] = { "wallet", "removeprunedfunds", &removeprunedfunds, true, {"txid"} }, { "wallet", "keepass", &keepass, true, {} }, - { "wallet", "instantsendtoaddress", &instantsendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} }, + { "hidden", "instantsendtoaddress", &instantsendtoaddress, false, {"address","amount","comment","comment_to","subtractfeefromamount"} }, { "wallet", "dumphdinfo", &dumphdinfo, true, {} }, { "wallet", "importelectrumwallet", &importelectrumwallet, true, {"filename", "index"} }, diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b5712e7ce7ba..976d55f7b5c0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -31,7 +31,6 @@ #include "utilmoneystr.h" #include "governance/governance.h" -#include "instantsend.h" #include "keepass.h" #include "privatesend/privatesend-client.h" #include "spork.h" @@ -1910,7 +1909,7 @@ void CWallet::ReacceptWalletTransactions() } } -bool CWalletTx::RelayWalletTransaction(CConnman* connman, const std::string& strCommand) +bool CWalletTx::RelayWalletTransaction(CConnman* connman) { assert(pwallet->GetBroadcastTransactions()); if (!IsCoinBase() && !isAbandoned() && GetDepthInMainChain() == 0) @@ -1921,15 +1920,6 @@ bool CWalletTx::RelayWalletTransaction(CConnman* connman, const std::string& str uint256 hash = GetHash(); LogPrintf("Relaying wtx %s\n", hash.ToString()); - if ((strCommand == NetMsgType::TXLOCKREQUEST) || - ((CTxLockRequest(*this).IsSimple()) && CInstantSend::CanAutoLock())) { - if (instantsend.ProcessTxLockRequest((CTxLockRequest)*this, *connman)) { - instantsend.AcceptLockRequest((CTxLockRequest)*this); - } else { - instantsend.RejectLockRequest((CTxLockRequest)*this); - } - } - if (connman) { connman->RelayTransaction((CTransaction)*this); return true; @@ -2540,13 +2530,12 @@ CAmount CWallet::GetLegacyBalance(const isminefilter& filter, int minDepth, cons return balance; } -void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t &nMaximumCount, const int &nMinDepth, const int &nMaxDepth, AvailableCoinsType nCoinType, bool fUseInstantSend) const +void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const CCoinControl *coinControl, const CAmount &nMinimumAmount, const CAmount &nMaximumAmount, const CAmount &nMinimumSumAmount, const uint64_t &nMaximumCount, const int &nMinDepth, const int &nMaxDepth, AvailableCoinsType nCoinType) const { vCoins.clear(); { LOCK2(cs_main, cs_wallet); - int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired; CAmount nTotal = 0; @@ -2562,9 +2551,6 @@ void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const continue; int nDepth = pcoin->GetDepthInMainChain(); - // do not use IX for inputs that have less then nInstantSendConfirmationsRequired blockchain confirmations - if (fUseInstantSend && nDepth < nInstantSendConfirmationsRequired) - continue; // We should not consider coins which aren't at least in our mempool // It's possible for these to be conflicted via ancestors which we may never be able to detect @@ -2638,19 +2624,13 @@ void CWallet::AvailableCoins(std::vector &vCoins, bool fOnlySafe, const } static void ApproximateBestSubset(const std::vector& vValue, const CAmount& nTotalLower, const CAmount& nTargetValue, - std::vector& vfBest, CAmount& nBest, bool fUseInstantSend = false, int iterations = 1000) + std::vector& vfBest, CAmount& nBest, int iterations = 1000) { std::vector vfIncluded; vfBest.assign(vValue.size(), true); nBest = nTotalLower; - if (!llmq::IsOldInstantSendEnabled()) { - // The new system does not require special handling for InstantSend as this is all done in CInstantSendManager. - // There is also no need for an extra fee anymore. - fUseInstantSend = false; - } - FastRandomContext insecure_rand; for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++) @@ -2662,9 +2642,6 @@ static void ApproximateBestSubset(const std::vector& vValue, const C { for (unsigned int i = 0; i < vValue.size(); i++) { - if (fUseInstantSend && nTotal + vValue[i].txout.nValue > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) { - continue; - } //The solver here uses a randomized algorithm, //the randomness serves no real security purpose but is just //needed to prevent degenerate behavior and it is important @@ -2718,27 +2695,16 @@ bool less_then_denom (const COutput& out1, const COutput& out2) } bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMine, const int nConfTheirs, const uint64_t nMaxAncestors, std::vector vCoins, - std::set& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType, bool fUseInstantSend) const + std::set& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType) const { setCoinsRet.clear(); nValueRet = 0; - if (!llmq::IsOldInstantSendEnabled()) { - // The new system does not require special handling for InstantSend as this is all done in CInstantSendManager. - // There is also no need for an extra fee anymore. - fUseInstantSend = false; - } - // List of values less than target boost::optional coinLowestLarger; std::vector vValue; CAmount nTotalLower = 0; - // TODO: drop SPORK_5_INSTANTSEND_MAX_VALUE spork - if (fUseInstantSend && nTargetValue > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE) * COIN && llmq::IsOldInstantSendEnabled()) { - return false; - } - random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); int tryDenomStart = 0; @@ -2845,9 +2811,9 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin std::vector vfBest; CAmount nBest; - ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, fUseInstantSend); + ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest); if (nBest != nTargetValue && nTotalLower >= nTargetValue + nMinChange) - ApproximateBestSubset(vValue, nTotalLower, nTargetValue + nMinChange, vfBest, nBest, fUseInstantSend); + ApproximateBestSubset(vValue, nTotalLower, nTargetValue + nMinChange, vfBest, nBest); // If we have a bigger coin and (either the stochastic approximation didn't find a good solution, // or the next bigger coin is closer), return the bigger coin @@ -2876,7 +2842,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin return nCoinType == ONLY_DENOMINATED ? (nValueRet - nTargetValue <= maxTxFee) : true; } -bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType nCoinType, bool fUseInstantSend) const +bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl, AvailableCoinsType nCoinType) const { // Note: this function should never be used for "always free" tx types like dstx @@ -2949,13 +2915,13 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm bool fRejectLongChains = gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS); bool res = nTargetValue <= nValueFromPresetInputs || - SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 6, 0, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend) || - SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 1, 0, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend) || - (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, 2, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)) || - (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::min((size_t)4, nMaxChainLength/3), vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)) || - (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength/2, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)) || - (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength, vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)) || - (bSpendZeroConfChange && !fRejectLongChains && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::numeric_limits::max(), vCoins, setCoinsRet, nValueRet, nCoinType, fUseInstantSend)); + SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 6, 0, vCoins, setCoinsRet, nValueRet, nCoinType) || + SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 1, 1, 0, vCoins, setCoinsRet, nValueRet, nCoinType) || + (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, 2, vCoins, setCoinsRet, nValueRet, nCoinType)) || + (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::min((size_t)4, nMaxChainLength/3), vCoins, setCoinsRet, nValueRet, nCoinType)) || + (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength/2, vCoins, setCoinsRet, nValueRet, nCoinType)) || + (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, nMaxChainLength, vCoins, setCoinsRet, nValueRet, nCoinType)) || + (bSpendZeroConfChange && !fRejectLongChains && SelectCoinsMinConf(nTargetValue - nValueFromPresetInputs, 0, 1, std::numeric_limits::max(), vCoins, setCoinsRet, nValueRet, nCoinType)); // because SelectCoinsMinConf clears the setCoinsRet, we now add the possible inputs to the coinset setCoinsRet.insert(setPresetCoins.begin(), setPresetCoins.end()); @@ -2994,7 +2960,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov CReserveKey reservekey(this); CWalletTx wtx; - if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false, ALL_COINS, false, nExtraPayloadSize)) + if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false, ALL_COINS, nExtraPayloadSize)) return false; if (nChangePosInOut != -1) @@ -3041,7 +3007,7 @@ bool CWallet::SelectPSInOutPairsByDenominations(int nDenom, CAmount nValueMin, C return false; } - AvailableCoins(vCoins, true, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_DENOMINATED, false); + AvailableCoins(vCoins, true, NULL, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, ONLY_DENOMINATED); LogPrintf("CWallet::%s -- vCoins.size(): %d\n", __func__, vCoins.size()); std::random_shuffle(vCoins.rbegin(), vCoins.rend(), GetRandInt); @@ -3356,7 +3322,7 @@ bool CWallet::CreateCollateralTransaction(CMutableTransaction& txCollateral, std return true; } -bool CWallet::GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, bool fUseInstantSend, const COutPoint& outpoint) +bool CWallet::GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, const COutPoint& outpoint) { // make our change address CReserveKey reservekey(this); @@ -3374,7 +3340,7 @@ bool CWallet::GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount a if (!outpoint.IsNull()) { coinControl.Select(outpoint); } - bool success = CreateTransaction(vecSend, tx, reservekey, nFeeRet, nChangePosRet, strFail, &coinControl, true, ALL_COINS, fUseInstantSend); + bool success = CreateTransaction(vecSend, tx, reservekey, nFeeRet, nChangePosRet, strFail, &coinControl, true, ALL_COINS); if(!success){ LogPrintf("CWallet::GetBudgetSystemCollateralTX -- Error: %s\n", strFail); return false; @@ -3402,16 +3368,8 @@ bool CWallet::ConvertList(std::vector vecTxIn, std::vector& vecA } bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, - int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign, AvailableCoinsType nCoinType, bool fUseInstantSend, int nExtraPayloadSize) + int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign, AvailableCoinsType nCoinType, int nExtraPayloadSize) { - if (!llmq::IsOldInstantSendEnabled()) { - // The new system does not require special handling for InstantSend as this is all done in CInstantSendManager. - // There is also no need for an extra fee anymore. - fUseInstantSend = false; - } - - CAmount nFeePay = fUseInstantSend ? CTxLockRequest().GetMinFee(true) : 0; - CAmount nValue = 0; int nChangePosRequest = nChangePosInOut; unsigned int nSubtractFeeFromAmount = 0; @@ -3476,11 +3434,9 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT LOCK2(cs_main, cs_wallet); { std::vector vAvailableCoins; - AvailableCoins(vAvailableCoins, true, coinControl, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, nCoinType, fUseInstantSend); - int nInstantSendConfirmationsRequired = Params().GetConsensus().nInstantSendConfirmationsRequired; + AvailableCoins(vAvailableCoins, true, coinControl, 1, MAX_MONEY, MAX_MONEY, 0, 0, 9999999, nCoinType); nFeeRet = 0; - if(nFeePay > 0) nFeeRet = nFeePay; // Start with no fee and loop until there is enough fee while (true) { @@ -3528,7 +3484,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // Choose coins to use CAmount nValueIn = 0; setCoins.clear(); - if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl, nCoinType, fUseInstantSend)) + if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoins, nValueIn, coinControl, nCoinType)) { if (nCoinType == ONLY_NONDENOMINATED) { strFailReason = _("Unable to locate enough PrivateSend non-denominated funds for this transaction."); @@ -3537,18 +3493,10 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT strFailReason += " " + _("PrivateSend uses exact denominated amounts to send funds, you might simply need to anonymize some more coins."); } else if (nValueIn < nValueToSelect) { strFailReason = _("Insufficient funds."); - if (fUseInstantSend) { - // could be not true but most likely that's the reason - strFailReason += " " + strprintf(_("InstantSend requires inputs with at least %d confirmations, you might need to wait a few minutes and try again."), nInstantSendConfirmationsRequired); - } } return false; } - if (fUseInstantSend && nValueIn > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) { - strFailReason += " " + strprintf(_("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH."), sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)); - return false; - } const CAmount nChange = nValueIn - nValueToSelect; CTxOut newTxOut; @@ -3716,10 +3664,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT if (coinControl && coinControl->nConfirmTarget > 0) currentConfirmationTarget = coinControl->nConfirmTarget; - CAmount nFeeNeeded = std::max(nFeePay, GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator)); - if(fUseInstantSend) { - nFeeNeeded = std::max(nFeeNeeded, CTxLockRequest(txNew).GetMinFee(true)); - } + CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, ::mempool, ::feeEstimator); if (coinControl && coinControl->fOverrideFeeRate) nFeeNeeded = coinControl->nFeeRate.GetFee(nBytes); @@ -3813,7 +3758,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT /** * Call after CreateTransaction unless you want to abort */ -bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state, const std::string& strCommand) +bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state) { { LOCK2(cs_main, cs_wallet); @@ -3851,7 +3796,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon LogPrintf("CommitTransaction(): Transaction cannot be broadcast immediately, %s\n", state.GetRejectReason()); // TODO: if we expect the failure to be long term or permanent, instead delete wtx from the wallet and return failure. } else { - wtxNew.RelayWalletTransaction(connman, strCommand); + wtxNew.RelayWalletTransaction(connman); } } } @@ -5389,11 +5334,6 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const } bool CMerkleTx::IsLockedByInstantSend() const -{ - return instantsend.IsLockedInstantSendTransaction(GetHash()) || llmq::quorumInstantSendManager->IsLocked(GetHash()); -} - -bool CMerkleTx::IsLockedByLLMQInstantSend() const { return llmq::quorumInstantSendManager->IsLocked(GetHash()); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 7eb94c2cdca4..283ead09236d 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -268,7 +268,6 @@ class CMerkleTx int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); } bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet) > 0; } bool IsLockedByInstantSend() const; - bool IsLockedByLLMQInstantSend() const; bool IsChainLocked() const; int GetBlocksToMaturity() const; /** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */ @@ -507,7 +506,7 @@ class CWalletTx : public CMerkleTx int64_t GetTxTime() const; int GetRequestCount() const; - bool RelayWalletTransaction(CConnman* connman, const std::string& strCommand="tx"); + bool RelayWalletTransaction(CConnman* connman); std::set GetConflicts() const; }; @@ -702,7 +701,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * all coins from coinControl are selected; Never select unconfirmed coins * if they are not ours */ - bool SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = true) const; + bool SelectCoins(const std::vector& vAvailableCoins, const CAmount& nTargetValue, std::set& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL, AvailableCoinsType nCoinType=ALL_COINS) const; CWalletDB *pwalletdbEncryption; @@ -883,7 +882,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface /** * populate vCoins with vector of available COutputs. */ - void AvailableCoins(std::vector& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 9999999, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = false) const; + void AvailableCoins(std::vector& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = NULL, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t& nMaximumCount = 0, const int& nMinDepth = 0, const int& nMaxDepth = 9999999, AvailableCoinsType nCoinType=ALL_COINS) const; /** * Shuffle and select coins until nTargetValue is reached while avoiding @@ -891,7 +890,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * completion the coin set and corresponding actual target value is * assembled */ - bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector vCoins, std::set& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend = false) const; + bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, uint64_t nMaxAncestors, std::vector vCoins, std::set& setCoinsRet, CAmount& nValueRet, AvailableCoinsType nCoinType=ALL_COINS) const; // Coin selection bool SelectPSInOutPairsByDenominations(int nDenom, CAmount nValueMin, CAmount nValueMax, std::vector< std::pair >& vecPSInOutPairsRet); @@ -1023,7 +1022,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface CAmount GetNormalizedAnonymizedBalance() const; CAmount GetDenominatedBalance(bool unconfirmed=false) const; - bool GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, bool fUseInstantSend, const COutPoint& outpoint=COutPoint()/*defaults null*/); + bool GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, const COutPoint& outpoint=COutPoint()/*defaults null*/); /** * Insert additional inputs into the transaction by @@ -1037,8 +1036,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface * @note passing nChangePosInOut as -1 will result in setting a random position */ bool CreateTransaction(const std::vector& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut, - std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true, AvailableCoinsType nCoinType=ALL_COINS, bool fUseInstantSend=false, int nExtraPayloadSize = 0); - bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state, const std::string& strCommand="tx"); + std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true, AvailableCoinsType nCoinType=ALL_COINS, int nExtraPayloadSize = 0); + bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CConnman* connman, CValidationState& state); bool CreateCollateralTransaction(CMutableTransaction& txCollateral, std::string& strReason); bool ConvertList(std::vector vecTxIn, std::vector& vecAmounts); diff --git a/src/zmq/zmqconfig.h b/src/zmq/zmqconfig.h index 0ce679fdfb63..c3122df6ec7d 100644 --- a/src/zmq/zmqconfig.h +++ b/src/zmq/zmqconfig.h @@ -22,8 +22,6 @@ #include "governance/governance-object.h" #include "governance/governance-vote.h" -#include "instantsend.h" - #include "llmq/quorums_chainlocks.h" #include "llmq/quorums_instantsend.h" diff --git a/test/functional/autois-mempool.py b/test/functional/autois-mempool.py deleted file mode 100755 index 71b23727defd..000000000000 --- a/test/functional/autois-mempool.py +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2018 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -from test_framework.mininode import * -from test_framework.test_framework import DashTestFramework -from test_framework.util import * -from time import * - -''' -autois-mempool.py - -Checks if automatic InstantSend locks stop working when transaction mempool -is full (more than 0.1 part from max value). - -''' - -MAX_MEMPOOL_SIZE = 1 # max node mempool in MBs -MB_SIZE = 1000000 # C++ code use this coefficient to calc MB in mempool -AUTO_IX_MEM_THRESHOLD = 0.1 - - -class AutoISMempoolTest(DashTestFramework): - def __init__(self): - super().__init__(8, 5, ["-maxmempool=%d" % MAX_MEMPOOL_SIZE, '-limitdescendantsize=10'], fast_dip3_enforcement=True) - # set sender, receiver - self.receiver_idx = 1 - self.sender_idx = 2 - - def get_mempool_usage(self, node): - info = node.getmempoolinfo() - return info['usage'] - - def fill_mempool(self): - # send lots of txes to yourself just to fill the mempool - counter = 0 - sync_period = 10 - dummy_address = self.nodes[0].getnewaddress() - while self.get_mempool_usage(self.nodes[self.sender_idx]) < MAX_MEMPOOL_SIZE * MB_SIZE * AUTO_IX_MEM_THRESHOLD: - self.nodes[0].sendtoaddress(dummy_address, 1.0) - counter += 1 - if counter % sync_period == 0: - # sync nodes - self.sync_all() - self.sync_all() - - def run_test(self): - # make sure masternodes are synced - sync_masternodes(self.nodes) - - self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0) - self.wait_for_sporks_same() - self.mine_quorum() - - self.log.info("Test old InstantSend") - self.test_auto(); - - # Generate 6 block to avoid retroactive signing overloading Travis - self.nodes[0].generate(6) - sync_blocks(self.nodes) - - self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0) - self.wait_for_sporks_same() - - self.log.info("Test new InstantSend") - self.test_auto(True); - - def test_auto(self, new_is = False): - self.activate_autois_bip9(self.nodes[0]) - self.set_autois_spork_state(self.nodes[0], True) - - # check pre-conditions for autoIS - assert(self.get_autois_bip9_status(self.nodes[0]) == 'active') - assert(self.get_autois_spork_state(self.nodes[0])) - - # create 3 inputs for txes on sender node and give them enough confirmations - sender = self.nodes[self.sender_idx] - receiver = self.nodes[self.receiver_idx] - sender_address = sender.getnewaddress() - for i in range(0, 4): - self.nodes[0].sendtoaddress(sender_address, 2.0) - for i in range(0, 2): - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - self.nodes[0].generate(1) - self.sync_all() - - # autoIS is working - assert(self.send_simple_tx(sender, receiver)) - - # fill mempool with transactions - self.set_autois_spork_state(self.nodes[0], False) - self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 4070908800) - self.wait_for_sporks_same() - self.fill_mempool() - self.set_autois_spork_state(self.nodes[0], True) - self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0) - self.wait_for_sporks_same() - - # autoIS is not working now - assert(not self.send_simple_tx(sender, receiver)) - # regular IS is still working for old IS but not for new one - assert(not self.send_regular_instantsend(sender, receiver, False) if new_is else self.send_regular_instantsend(sender, receiver)) - - # generate one block to clean up mempool and retry auto and regular IS - # generate 5 more blocks to avoid retroactive signing (which would overload Travis) - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 4070908800) - self.wait_for_sporks_same() - self.nodes[0].generate(6) - self.sync_all() - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0) - self.wait_for_sporks_same() - assert(self.send_simple_tx(sender, receiver)) - assert(self.send_regular_instantsend(sender, receiver, not new_is)) - - -if __name__ == '__main__': - AutoISMempoolTest().main() diff --git a/test/functional/dip3-deterministicmns.py b/test/functional/dip3-deterministicmns.py index 99403686d793..3ebc397a6ed1 100755 --- a/test/functional/dip3-deterministicmns.py +++ b/test/functional/dip3-deterministicmns.py @@ -114,9 +114,6 @@ def run_test(self): self.sync_all() self.assert_mnlists(mns) - self.log.info("testing instant send") - self.test_instantsend(10, 3) - self.log.info("test that MNs disappear from the list when the ProTx collateral is spent") spend_mns_count = 3 mns_tmp = [] + mns @@ -191,9 +188,6 @@ def run_test(self): self.start_mn(new_mn) self.sync_all() - self.log.info("testing instant send with replaced MNs") - self.test_instantsend(10, 3, timeout=20) - def prepare_mn(self, node, idx, alias): mn = Masternode() mn.idx = idx @@ -306,57 +300,6 @@ def force_finish_mnsync_list(self, node): return time.sleep(0.1) - def test_instantsend(self, tx_count, repeat, timeout=20): - self.nodes[0].spork('SPORK_2_INSTANTSEND_ENABLED', 0) - self.wait_for_sporks() - - # give all nodes some coins first - for i in range(tx_count): - outputs = {} - for node in self.nodes[1:]: - outputs[node.getnewaddress()] = 1 - rawtx = self.nodes[0].createrawtransaction([], outputs) - rawtx = self.nodes[0].fundrawtransaction(rawtx)['hex'] - rawtx = self.nodes[0].signrawtransaction(rawtx)['hex'] - self.nodes[0].sendrawtransaction(rawtx) - self.nodes[0].generate(1) - self.sync_all() - - for j in range(repeat): - for i in range(tx_count): - while True: - from_node_idx = random.randint(1, len(self.nodes) - 1) - from_node = self.nodes[from_node_idx] - if from_node is not None: - break - while True: - to_node_idx = random.randint(0, len(self.nodes) - 1) - to_node = self.nodes[to_node_idx] - if to_node is not None and from_node is not to_node: - break - to_address = to_node.getnewaddress() - txid = from_node.instantsendtoaddress(to_address, 0.1) - for node in self.nodes: - if node is not None: - self.wait_for_instant_lock(node, to_node_idx, txid, timeout=timeout) - self.nodes[0].generate(6) - self.sync_all() - - def wait_for_instant_lock(self, node, node_idx, txid, timeout=10): - st = time.time() - while time.time() < st + timeout: - try: - tx = node.getrawtransaction(txid, 1) - except: - tx = None - if tx is None: - time.sleep(0.5) - continue - if tx['instantlock']: - return - time.sleep(0.5) - raise AssertionError("wait_for_instant_lock timed out for: {} on node {}".format(txid, node_idx)) - def assert_mnlists(self, mns): for node in self.nodes: self.assert_mnlist(node, mns) diff --git a/test/functional/llmq-chainlocks.py b/test/functional/llmq-chainlocks.py index cca1f9074162..11eee59922d3 100755 --- a/test/functional/llmq-chainlocks.py +++ b/test/functional/llmq-chainlocks.py @@ -91,7 +91,8 @@ def run_test(self): assert(self.nodes[0].getbestblockhash() == self.nodes[1].getbestblockhash()) # Enable LLMQ bases InstantSend, which also enables checks for "safe" transactions - self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0) + self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0) + self.nodes[0].spork("SPORK_3_INSTANTSEND_BLOCK_FILTERING", 0) self.wait_for_sporks_same() # Isolate a node and let it create some transactions which won't get IS locked @@ -108,10 +109,10 @@ def run_test(self): sleep(1) assert(not self.nodes[0].getblock(self.nodes[0].getbestblockhash())["chainlock"]) # Disable LLMQ based InstantSend for a very short time (this never gets propagated to other nodes) - self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 4070908800) + self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 4070908800) # Now the TXs should be included self.nodes[0].generate(1) - self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0) + self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0) # Assert that TXs got included now for txid in txs: tx = self.nodes[0].getrawtransaction(txid, 1) diff --git a/test/functional/llmq-is-cl-conflicts.py b/test/functional/llmq-is-cl-conflicts.py index f376f3b7d68e..17d2d035d32b 100755 --- a/test/functional/llmq-is-cl-conflicts.py +++ b/test/functional/llmq-is-cl-conflicts.py @@ -61,7 +61,8 @@ def run_test(self): self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0) self.nodes[0].spork("SPORK_19_CHAINLOCKS_ENABLED", 0) - self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0) + self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0) + self.nodes[0].spork("SPORK_3_INSTANTSEND_BLOCK_FILTERING", 0) self.wait_for_sporks_same() self.mine_quorum() diff --git a/test/functional/multikeysporks.py b/test/functional/multikeysporks.py index df1764b0603f..1ea37d1b5923 100755 --- a/test/functional/multikeysporks.py +++ b/test/functional/multikeysporks.py @@ -119,7 +119,7 @@ def wait_for_test_spork_state(self, node, value): def run_test(self): # check test spork default state for node in self.nodes: - assert(self.get_test_spork_state(node) == 0) + assert(self.get_test_spork_state(node) == 4070908800) set_mocktime(get_mocktime() + 1) set_node_times(self.nodes, get_mocktime()) diff --git a/test/functional/p2p-autoinstantsend.py b/test/functional/p2p-autoinstantsend.py deleted file mode 100755 index 707265a1c262..000000000000 --- a/test/functional/p2p-autoinstantsend.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2018 The Dash Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -from test_framework.mininode import * -from test_framework.test_framework import DashTestFramework -from test_framework.util import * -from time import * - -''' -p2p-autoinstantsend.py - -Test automatic InstantSend locks functionality. - -Checks that simple transactions automatically become InstantSend locked, -complex transactions don't become IS-locked and this functionality is -activated only if SPORK_16_INSTANTSEND_AUTOLOCKS is active. - -Also checks that this functionality doesn't influence regular InstantSend -transactions with high fee. -''' - -class AutoInstantSendTest(DashTestFramework): - def __init__(self): - super().__init__(8, 5, [], fast_dip3_enforcement=True) - # set sender, receiver, isolated nodes - self.receiver_idx = 1 - self.sender_idx = 2 - - def run_test(self): - # make sure masternodes are synced - sync_masternodes(self.nodes) - - self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0) - self.wait_for_sporks_same() - self.mine_quorum() - - self.log.info("Test old InstantSend") - self.test_auto(); - - # Generate 6 block to avoid retroactive signing overloading Travis - self.nodes[0].generate(6) - sync_blocks(self.nodes) - - self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0) - self.wait_for_sporks_same() - - self.log.info("Test new InstantSend") - self.test_auto(True); - - def test_auto(self, new_is = False): - sender = self.nodes[self.sender_idx] - receiver = self.nodes[self.receiver_idx] - # feed the sender with some balance, make sure there are enough inputs - recipients = {} - for i in range(0, 30): - recipients[sender.getnewaddress()] = 1 - # use a single transaction to not overload Travis with InstantSend - self.nodes[0].sendmany("", recipients) - - # make sender funds mature for InstantSend - for i in range(0, 2): - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - self.nodes[0].generate(1) - self.sync_all() - - assert(not self.get_autois_spork_state(self.nodes[0])) - - assert(self.send_regular_instantsend(sender, receiver, not new_is)) - assert(self.send_simple_tx(sender, receiver) if new_is else not self.send_simple_tx(sender, receiver)) - assert(self.send_complex_tx(sender, receiver) if new_is else not self.send_complex_tx(sender, receiver)) - - self.activate_autois_bip9(self.nodes[0]) - self.set_autois_spork_state(self.nodes[0], True) - - assert(self.get_autois_bip9_status(self.nodes[0]) == 'active') - assert(self.get_autois_spork_state(self.nodes[0])) - - assert(self.send_regular_instantsend(sender, receiver, not new_is)) - assert(self.send_simple_tx(sender, receiver)) - assert(self.send_complex_tx(sender, receiver) if new_is else not self.send_complex_tx(sender, receiver)) - - self.set_autois_spork_state(self.nodes[0], False) - assert(not self.get_autois_spork_state(self.nodes[0])) - - assert(self.send_regular_instantsend(sender, receiver, not new_is)) - assert(self.send_simple_tx(sender, receiver) if new_is else not self.send_simple_tx(sender, receiver)) - assert(self.send_complex_tx(sender, receiver) if new_is else not self.send_complex_tx(sender, receiver)) - - # mine all mempool txes - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - self.nodes[0].generate(1) - self.sync_all() - -if __name__ == '__main__': - AutoInstantSendTest().main() diff --git a/test/functional/p2p-instantsend.py b/test/functional/p2p-instantsend.py index 03a078d09476..d0d4171ef92c 100755 --- a/test/functional/p2p-instantsend.py +++ b/test/functional/p2p-instantsend.py @@ -25,17 +25,10 @@ def run_test(self): self.wait_for_sporks_same() self.mine_quorum() - self.log.info("Test old InstantSend") - self.test_block_doublespend() - - # Generate 6 block to avoid retroactive signing overloading Travis - self.nodes[0].generate(6) - sync_blocks(self.nodes) - - self.nodes[0].spork("SPORK_20_INSTANTSEND_LLMQ_BASED", 0) + self.nodes[0].spork("SPORK_2_INSTANTSEND_ENABLED", 0) + self.nodes[0].spork("SPORK_3_INSTANTSEND_BLOCK_FILTERING", 0) self.wait_for_sporks_same() - self.log.info("Test new InstantSend") self.test_mempool_doublespend() self.test_block_doublespend() @@ -56,7 +49,7 @@ def test_block_doublespend(self): isolate_node(isolated) # instantsend to receiver receiver_addr = receiver.getnewaddress() - is_id = sender.instantsendtoaddress(receiver_addr, 0.9) + is_id = sender.sendtoaddress(receiver_addr, 0.9) for node in self.nodes: if node is not isolated: self.wait_for_instantlock(is_id, node) @@ -112,7 +105,7 @@ def test_mempool_doublespend(self): # instantsend to receiver. The previously isolated node should prune the doublespend TX and request the correct # TX from other nodes. receiver_addr = receiver.getnewaddress() - is_id = sender.instantsendtoaddress(receiver_addr, 0.9) + is_id = sender.sendtoaddress(receiver_addr, 0.9) for node in self.nodes: self.wait_for_instantlock(is_id, node) assert_raises_jsonrpc(-5, "No such mempool or blockchain transaction", isolated.getrawtransaction, dblspnd_txid) diff --git a/test/functional/sporks.py b/test/functional/sporks.py index b72045bfc18d..e7b21ef0998c 100755 --- a/test/functional/sporks.py +++ b/test/functional/sporks.py @@ -39,16 +39,16 @@ def set_test_spork_state(self, node, state): def run_test(self): # check test spork default state - assert(self.get_test_spork_state(self.nodes[0])) - assert(self.get_test_spork_state(self.nodes[1])) - assert(self.get_test_spork_state(self.nodes[2])) + assert(not self.get_test_spork_state(self.nodes[0])) + assert(not self.get_test_spork_state(self.nodes[1])) + assert(not self.get_test_spork_state(self.nodes[2])) # check spork propagation for connected nodes - self.set_test_spork_state(self.nodes[0], False) + self.set_test_spork_state(self.nodes[0], True) start = time() sent = False while True: - if not self.get_test_spork_state(self.nodes[1]): + if self.get_test_spork_state(self.nodes[1]): sent = True break if time() > start + 10: @@ -61,8 +61,8 @@ def run_test(self): self.stop_node(1) self.nodes[0] = self.start_node(0, self.options.tmpdir) self.nodes[1] = self.start_node(1, self.options.tmpdir) - assert(not self.get_test_spork_state(self.nodes[0])) - assert(not self.get_test_spork_state(self.nodes[1])) + assert(self.get_test_spork_state(self.nodes[0])) + assert(self.get_test_spork_state(self.nodes[1])) # Force finish mnsync node as otherwise it will never send out headers to other peers wait_to_sync(self.nodes[1], fast_mnsync=True) @@ -75,7 +75,7 @@ def run_test(self): start = time() sent = False while True: - if not self.get_test_spork_state(self.nodes[2]): + if self.get_test_spork_state(self.nodes[2]): sent = True break if time() > start + 10: diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 7d6f94cad481..a663482eb392 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -549,66 +549,6 @@ def setup_network(self): for status in mn_info.values(): assert (status == 'ENABLED') - def get_autois_bip9_status(self, node): - info = node.getblockchaininfo() - # we reuse the dip3 deployment - return info['bip9_softforks']['dip0003']['status'] - - def activate_autois_bip9(self, node): - # sync nodes periodically - # if we sync them too often, activation takes too many time - # if we sync them too rarely, nodes failed to update its state and - # bip9 status is not updated - # so, in this code nodes are synced once per 20 blocks - counter = 0 - sync_period = 10 - - while self.get_autois_bip9_status(node) == 'defined': - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - node.generate(1) - counter += 1 - if counter % sync_period == 0: - # sync nodes - self.sync_all() - - while self.get_autois_bip9_status(node) == 'started': - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - node.generate(1) - counter += 1 - if counter % sync_period == 0: - # sync nodes - self.sync_all() - - while self.get_autois_bip9_status(node) == 'locked_in': - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - node.generate(1) - counter += 1 - if counter % sync_period == 0: - # sync nodes - self.sync_all() - - # sync nodes - self.sync_all() - - assert(self.get_autois_bip9_status(node) == 'active') - - def get_autois_spork_state(self, node): - info = node.spork('active') - return info['SPORK_16_INSTANTSEND_AUTOLOCKS'] - - def set_autois_spork_state(self, node, state): - # Increment mocktime as otherwise nodes will not update sporks - set_mocktime(get_mocktime() + 1) - set_node_times(self.nodes, get_mocktime()) - if state: - value = 0 - else: - value = 4070908800 - node.spork('SPORK_16_INSTANTSEND_AUTOLOCKS', value) - def create_raw_tx(self, node_from, node_to, amount, min_inputs, max_inputs): assert (min_inputs <= max_inputs) # fill inputs @@ -656,31 +596,6 @@ def create_raw_tx(self, node_from, node_to, amount, min_inputs, max_inputs): ret = {**decoded, **ret} return ret - # sends regular instantsend with high fee - def send_regular_instantsend(self, sender, receiver, check_fee = True): - receiver_addr = receiver.getnewaddress() - txid = sender.instantsendtoaddress(receiver_addr, 1.0) - if (check_fee): - MIN_FEE = satoshi_round(-0.0001) - fee = sender.gettransaction(txid)['fee'] - expected_fee = MIN_FEE * len(sender.getrawtransaction(txid, True)['vin']) - assert_equal(fee, expected_fee) - return self.wait_for_instantlock(txid, sender) - - # sends simple tx, it should become locked if autolocks are allowed - def send_simple_tx(self, sender, receiver): - raw_tx = self.create_raw_tx(sender, receiver, 1.0, 1, 4) - txid = self.nodes[0].sendrawtransaction(raw_tx['hex']) - self.sync_all() - return self.wait_for_instantlock(txid, sender) - - # sends complex tx, it should never become locked for old instentsend - def send_complex_tx(self, sender, receiver): - raw_tx = self.create_raw_tx(sender, receiver, 1.0, 5, 100) - txid = sender.sendrawtransaction(raw_tx['hex']) - self.sync_all() - return self.wait_for_instantlock(txid, sender) - def wait_for_instantlock(self, txid, node): # wait for instantsend locks start = time.time() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 041890cd03c6..5fabd71e7648 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -60,8 +60,6 @@ 'p2p-fullblocktest.py', # NOTE: needs dash_hash to pass 'fundrawtransaction.py', 'fundrawtransaction-hd.py', - 'p2p-autoinstantsend.py', - 'autois-mempool.py', # vv Tests less than 2m vv 'p2p-instantsend.py', 'wallet.py', From e80ca5361c9250bec7ba16a538a7ab5a1c48eda4 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 12 Jun 2017 16:15:53 +0200 Subject: [PATCH 366/987] Merge #10549: Avoid printing generic and duplicated "checking for QT" during ./configure 7222388 Avoid printing generic and duplicated "checking for QT" during ./configure (Timothy Redaelli) Tree-SHA512: 2c52d5b5f55aa18abba9db100f3163be572219cb0dca928f33e9757b92608d3fb330d5c35c45ffcd7599a21163bf7e6cffdb53abe206cc44317862836efc5329 --- build-aux/m4/bitcoin_qt.m4 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4 index c3785bdcf3b7..f9d63864eb8e 100644 --- a/build-aux/m4/bitcoin_qt.m4 +++ b/build-aux/m4/bitcoin_qt.m4 @@ -414,17 +414,17 @@ AC_DEFUN([_BITCOIN_QT_FIND_LIBS_WITH_PKGCONFIG],[ qt4_modules="QtCore QtGui QtNetwork" BITCOIN_QT_CHECK([ if test x$bitcoin_qt_want_version = xqt5 || ( test x$bitcoin_qt_want_version = xauto && test x$auto_priority_version = xqt5 ); then - PKG_CHECK_MODULES([QT], [$qt5_modules], [QT_INCLUDES="$QT_CFLAGS"; have_qt=yes],[have_qt=no]) + PKG_CHECK_MODULES([QT5], [$qt5_modules], [QT_INCLUDES="$QT5_CFLAGS"; QT_LIBS="$QT5_LIBS" have_qt=yes],[have_qt=no]) elif test x$bitcoin_qt_want_version = xqt4 || ( test x$bitcoin_qt_want_version = xauto && test x$auto_priority_version = xqt4 ); then - PKG_CHECK_MODULES([QT], [$qt4_modules], [QT_INCLUDES="$QT_CFLAGS"; have_qt=yes], [have_qt=no]) + PKG_CHECK_MODULES([QT4], [$qt4_modules], [QT_INCLUDES="$QT4_CFLAGS"; QT_LIBS="$QT4_LIBS" ; have_qt=yes], [have_qt=no]) fi dnl qt version is set to 'auto' and the preferred version wasn't found. Now try the other. if test x$have_qt = xno && test x$bitcoin_qt_want_version = xauto; then if test x$auto_priority_version = xqt5; then - PKG_CHECK_MODULES([QT], [$qt4_modules], [QT_INCLUDES="$QT_CFLAGS"; have_qt=yes; QT_LIB_PREFIX=Qt; bitcoin_qt_got_major_vers=4], [have_qt=no]) + PKG_CHECK_MODULES([QT4], [$qt4_modules], [QT_INCLUDES="$QT4_CFLAGS"; QT_LIBS="$QT4_LIBS" ; have_qt=yes; QT_LIB_PREFIX=Qt; bitcoin_qt_got_major_vers=4], [have_qt=no]) else - PKG_CHECK_MODULES([QT], [$qt5_modules], [QT_INCLUDES="$QT_CFLAGS"; have_qt=yes; QT_LIB_PREFIX=Qt5; bitcoin_qt_got_major_vers=5], [have_qt=no]) + PKG_CHECK_MODULES([QT5], [$qt5_modules], [QT_INCLUDES="$QT5_CFLAGS"; QT_LIBS="$QT5_LIBS" ; have_qt=yes; QT_LIB_PREFIX=Qt5; bitcoin_qt_got_major_vers=5], [have_qt=no]) fi fi if test x$have_qt != xyes; then From 30c5aaead12d8d0e78d3472d754bf2c92a26e6f6 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 12 Jun 2017 15:02:22 -0700 Subject: [PATCH 367/987] Merge #10578: Add missing include for atomic in db.h 8e69adc66 Add missing include for atomic in db.h (Alex Morcos) Tree-SHA512: 1fb9a8b3eb6238f3ee754d94cf1424fd51bbb2ec6780dcb50fdc3f190fd6c2e8567b5f01b25c4197b86ee684eddcf345d24723220154cf595e3b96ad24e611ac --- src/wallet/db.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wallet/db.h b/src/wallet/db.h index e4d8a5154d13..d5ff62d18790 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -13,6 +13,7 @@ #include "sync.h" #include "version.h" +#include #include #include #include From 195d42a2841ff4605536ea8696775fa721ebe470 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 12 Jun 2017 15:09:07 -0700 Subject: [PATCH 368/987] Merge #10568: Remove unnecessary forward class declarations in header files 4087d9ea7 Remove unnecessary forward class declarations in header files (practicalswift) Tree-SHA512: 80a9b2cd339ba9c606c0dd93739ac80941b6050388fee2edd7976ae8b5e332fd0b4f1df1e89c1d6d28a77c23a36b1e874e72977985fb8f710c65c45c3a926f97 --- src/httprpc.h | 2 -- src/miner.h | 2 -- src/net.h | 1 - src/qt/addressbookpage.h | 2 -- src/qt/bitcoingui.h | 2 -- src/qt/clientmodel.h | 3 --- src/qt/coincontroldialog.h | 1 - src/qt/receivecoinsdialog.h | 1 - src/qt/sendcoinsdialog.h | 1 - src/qt/utilitydialog.h | 1 - src/rpc/blockchain.h | 3 --- src/rpc/server.h | 3 --- src/txmempool.h | 1 - src/ui_interface.h | 2 -- src/validation.h | 2 -- src/wallet/crypter.h | 2 -- 16 files changed, 29 deletions(-) diff --git a/src/httprpc.h b/src/httprpc.h index d35445718871..a89a8f0fbfe0 100644 --- a/src/httprpc.h +++ b/src/httprpc.h @@ -8,8 +8,6 @@ #include #include -class HTTPRequest; - /** Start HTTP RPC subsystem. * Precondition; HTTP and RPC has been started. */ diff --git a/src/miner.h b/src/miner.h index 995cce10c747..0fd97c20e1b5 100644 --- a/src/miner.h +++ b/src/miner.h @@ -17,9 +17,7 @@ class CBlockIndex; class CChainParams; class CConnman; -class CReserveKey; class CScript; -class CWallet; namespace Consensus { struct Params; }; diff --git a/src/net.h b/src/net.h index 6d648d5bd8b1..8d22b6c4a729 100644 --- a/src/net.h +++ b/src/net.h @@ -125,7 +125,6 @@ struct AddedNodeInfo bool fInbound; }; -class CTransaction; class CNodeStats; class CClientUIInterface; diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 55e8101a412c..93911a1ff8dd 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -8,7 +8,6 @@ #include class AddressTableModel; -class OptionsModel; class PlatformStyle; namespace Ui { @@ -20,7 +19,6 @@ class QItemSelection; class QMenu; class QModelIndex; class QSortFilterProxyModel; -class QTableView; QT_END_NAMESPACE /** Widget that shows a list of sending or receiving addresses. diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index e01da23c4e83..df1fd19933ea 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -32,8 +32,6 @@ class WalletModel; class HelpMessageDialog; class ModalOverlay; -class CWallet; - QT_BEGIN_NAMESPACE class QAction; class QProgressBar; diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 9c86be225683..5fb12ec21d57 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -14,13 +14,10 @@ #include -class AddressTableModel; class BanTableModel; class OptionsModel; class PeerTableModel; -class TransactionTableModel; -class CWallet; class CBlockIndex; QT_BEGIN_NAMESPACE diff --git a/src/qt/coincontroldialog.h b/src/qt/coincontroldialog.h index 594a68fee897..2940ab3bd24a 100644 --- a/src/qt/coincontroldialog.h +++ b/src/qt/coincontroldialog.h @@ -20,7 +20,6 @@ class PlatformStyle; class WalletModel; class CCoinControl; -class CTxMemPool; namespace Ui { class CoinControlDialog; diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index ac85c50f4d18..488741d654c2 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -15,7 +15,6 @@ #include #include -class OptionsModel; class PlatformStyle; class WalletModel; diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index ae34d1e6a93b..403d90bc5f8b 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -15,7 +15,6 @@ static const int MAX_SEND_POPUP_ENTRIES = 10; class ClientModel; -class OptionsModel; class PlatformStyle; class SendCoinsEntry; class SendCoinsRecipient; diff --git a/src/qt/utilitydialog.h b/src/qt/utilitydialog.h index c3493ac28bb8..c1c95dcb55c4 100644 --- a/src/qt/utilitydialog.h +++ b/src/qt/utilitydialog.h @@ -9,7 +9,6 @@ #include class BitcoinGUI; -class ClientModel; namespace Ui { class HelpMessageDialog; diff --git a/src/rpc/blockchain.h b/src/rpc/blockchain.h index c021441b0a73..960edfd56f5b 100644 --- a/src/rpc/blockchain.h +++ b/src/rpc/blockchain.h @@ -7,9 +7,6 @@ class CBlock; class CBlockIndex; -class CScript; -class CTransaction; -class uint256; class UniValue; /** diff --git a/src/rpc/server.h b/src/rpc/server.h index de3b74ead22d..f2f1dd2a9270 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -26,9 +26,6 @@ namespace RPCServer void OnPreCommand(std::function slot); } -class CBlockIndex; -class CNetAddr; - /** Wrapper for UniValue::VType, which includes typeAny: * Used to denote don't care type. Only used by RPCTypeCheckObj */ struct UniValueType { diff --git a/src/txmempool.h b/src/txmempool.h index 04b6587bd03d..64f032534eaa 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -33,7 +33,6 @@ #include -class CAutoFile; class CBlockIndex; /** Fake height value used in Coin to signify they are only in the memory pool (since 0.8) */ diff --git a/src/ui_interface.h b/src/ui_interface.h index cb07bc0c867c..bbe25b5caaae 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -12,9 +12,7 @@ #include #include -class CBasicKeyStore; class CWallet; -class uint256; class CBlockIndex; class CDeterministicMNList; diff --git a/src/validation.h b/src/validation.h index ade1a3cd3fc9..cd6c592247cd 100644 --- a/src/validation.h +++ b/src/validation.h @@ -34,7 +34,6 @@ class CBlockIndex; class CBlockTreeDB; -class CBloomFilter; class CChainParams; class CCoinsViewDB; class CInv; @@ -42,7 +41,6 @@ class CConnman; class CScriptCheck; class CBlockPolicyEstimator; class CTxMemPool; -class CValidationInterface; class CValidationState; class PrecomputedTransactionData; struct ChainTxData; diff --git a/src/wallet/crypter.h b/src/wallet/crypter.h index 1b5cdbcffcb8..d8012537db1d 100644 --- a/src/wallet/crypter.h +++ b/src/wallet/crypter.h @@ -9,8 +9,6 @@ #include "serialize.h" #include "support/allocators/secure.h" -class uint256; - const unsigned int WALLET_CRYPTO_KEY_SIZE = 32; const unsigned int WALLET_CRYPTO_SALT_SIZE = 8; const unsigned int WALLET_CRYPTO_IV_SIZE = 16; From eef9c8ea15fca2aabd0e4396516220bf82a16d58 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 13 Jun 2017 09:20:23 +0200 Subject: [PATCH 369/987] Merge #10553: Simplify "bool x = y ? true : false". Remove unused function and trailing semicolon. 67ca816 Simplify "bool x = y ? true : false" to "bool x = y" (practicalswift) 9f841a6 [tests] Remove accidental trailing semicolon (practicalswift) 30c2d9d [tests] Remove unused function InsecureRandBytes(size_t len) (practicalswift) Tree-SHA512: ae62c255c88133cad12084b6011c105bb96b729c8103330350683d9c20020c5d7617693795df4dff6cc305f2405cb2e4e2ece182d6e6d7c3c8db82aa2f882c41 --- src/blockencodings.cpp | 2 +- src/rpc/misc.cpp | 4 ++-- src/test/miner_tests.cpp | 6 +++--- src/test/test_dash.h | 1 - 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/blockencodings.cpp b/src/blockencodings.cpp index 02cac61e741d..3e2d40844ca6 100644 --- a/src/blockencodings.cpp +++ b/src/blockencodings.cpp @@ -172,7 +172,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c bool PartiallyDownloadedBlock::IsTxAvailable(size_t index) const { assert(!header.IsNull()); assert(index < txn_available.size()); - return txn_available[index] ? true : false; + return txn_available[index] != nullptr; } ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector& vtx_missing) { diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index c8d6ef003a42..41fda5f9b284 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -371,8 +371,8 @@ UniValue validateaddress(const JSONRPCRequest& request) #ifdef ENABLE_WALLET isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO; - ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false)); - ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false)); + ret.push_back(Pair("ismine", bool(mine & ISMINE_SPENDABLE))); + ret.push_back(Pair("iswatchonly", bool(mine & ISMINE_WATCH_ONLY))); UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest); ret.pushKVs(detail); if (pwallet && pwallet->mapAddressBook.count(dest)) { diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 3f860cffdaec..dcab00ca5a95 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -279,7 +279,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase + bool spendsCoinbase = i == 0; // only first tx spends coinbase // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; @@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase + bool spendsCoinbase = i == 0; // only first tx spends coinbase // If we do set the # of sig ops in the CTxMemPoolEntry, template creation passes mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).SigOps(20).FromTx(tx)); tx.vin[0].prevout.hash = hash; @@ -314,7 +314,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) { tx.vout[0].nValue -= LOWFEE; hash = tx.GetHash(); - bool spendsCoinbase = (i == 0) ? true : false; // only first tx spends coinbase + bool spendsCoinbase = i == 0; // only first tx spends coinbase mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx)); tx.vin[0].prevout.hash = hash; } diff --git a/src/test/test_dash.h b/src/test/test_dash.h index c5babca70c91..be3a0c94d8a2 100644 --- a/src/test/test_dash.h +++ b/src/test/test_dash.h @@ -34,7 +34,6 @@ static inline uint256 InsecureRand256() { return insecure_rand_ctx.rand256(); } static inline uint64_t InsecureRandBits(int bits) { return insecure_rand_ctx.randbits(bits); } static inline uint64_t InsecureRandRange(uint64_t range) { return insecure_rand_ctx.randrange(range); } static inline bool InsecureRandBool() { return insecure_rand_ctx.randbool(); } -static inline std::vector InsecureRandBytes(size_t len) { return insecure_rand_ctx.randbytes(len); } /** Basic testing setup. * This just configures logging and chain parameters. From c1c24205b7124154f28679f3afdaf3465a4acc2a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 13 Jun 2017 18:28:24 +0200 Subject: [PATCH 370/987] Merge #10534: Clarify prevector::erase and avoid swap-to-clear e241a63 Clarify prevector::erase and avoid swap-to-clear (Pieter Wuille) Tree-SHA512: fa7602038feb4417158df13ee7c0351673acf38f8a824e75889710344c46a9b8d5f6059faeb521f73e48b7ad3e1a238a9e433e4b44f7c3b9085ff08ef65271fa --- src/prevector.h | 6 ++++++ src/script/script.h | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/prevector.h b/src/prevector.h index 717d42f92b68..597838a175c1 100644 --- a/src/prevector.h +++ b/src/prevector.h @@ -387,6 +387,12 @@ class prevector { } iterator erase(iterator first, iterator last) { + // Erase is not allowed to the change the object's capacity. That means + // that when starting with an indirectly allocated prevector with + // size and capacity > N, the result may be a still indirectly allocated + // prevector with size <= N and capacity > N. A shrink_to_fit() call is + // necessary to switch to the (more efficient) directly allocated + // representation (with capacity N and size <= N). iterator p = first; char* endp = (char*)&(*end()); if (!std::is_trivially_destructible::value) { diff --git a/src/script/script.h b/src/script/script.h index 9a276ed3fe1b..77eb896503bc 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -645,8 +645,9 @@ class CScript : public CScriptBase void clear() { - // The default std::vector::clear() does not release memory. - CScriptBase().swap(*this); + // The default prevector::clear() does not release memory + CScriptBase::clear(); + shrink_to_fit(); } template From 10716ea6dd0b769ddda91cb4bb0defd0950df8a2 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 13 Jun 2017 19:09:59 +0200 Subject: [PATCH 371/987] Merge #10575: Header include guideline a090d1c Header include guideline (Pieter Wuille) Tree-SHA512: 44c46a3e249c946303b0fa45ddeba1abc40ec4f993b78f10894d6f43de2b62c493d74f8a24b5b69d3c71cd5c1b3cdb638c8eabdade3dc60e376bc933a8f10940 --- doc/developer-notes.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index 0be01417ef3c..d0f6e2773ea0 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -404,6 +404,14 @@ Source code organization - *Rationale*: Shorter and simpler header files are easier to read, and reduce compile time +- Every `.cpp` and `.h` file should `#include` every header file it directly uses classes, functions or other + definitions from, even if those headers are already included indirectly through other headers. One exception + is that a `.cpp` file does not need to re-include the includes already included in its corresponding `.h` file. + + - *Rationale*: Excluding headers because they are already indirectly included results in compilation + failures when those indirect dependencies change. Furthermore, it obscures what the real code + dependencies are. + - Don't import anything into the global namespace (`using namespace ...`). Use fully specified types such as `std::string`. From 946388169dcafdf56c9e76050b72cede2bb67a8a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 13 Jun 2017 19:38:37 +0200 Subject: [PATCH 372/987] Merge #10544: Update to LevelDB 1.20 3ee3d04 Add extra LevelDB source to Makefile (MarcoFalke) 2424989 leveldb: enable runtime-detected crc32 instructions (Cory Fields) cf44e4c Squashed 'src/leveldb/' changes from a31c8aa40..196962ff0 (Pieter Wuille) Tree-SHA512: 19ade77e3f6265507b3ab7b9aa5150d378aa0751e24ac7a61567b0f720a566cedc6c3d3336da17a3bd2b5d068ee86600d96a15228f78bd20ccf98c8fc9041a91 --- configure.ac | 8 + src/Makefile.am | 1 + src/Makefile.bench.include | 1 + src/Makefile.leveldb.include | 12 + src/Makefile.qt.include | 2 +- src/Makefile.qttest.include | 2 +- src/Makefile.test.include | 4 +- src/leveldb/Makefile | 12 +- src/leveldb/README.md | 25 +- src/leveldb/build_detect_platform | 30 +- src/leveldb/db/db_bench.cc | 38 +- src/leveldb/db/db_impl.cc | 1 + src/leveldb/db/log_format.h | 2 +- src/leveldb/db/version_set.cc | 57 ++- src/leveldb/db/version_set.h | 2 +- src/leveldb/doc/doc.css | 89 ---- src/leveldb/doc/impl.html | 213 --------- src/leveldb/doc/impl.md | 170 +++++++ src/leveldb/doc/index.html | 549 ----------------------- src/leveldb/doc/index.md | 523 +++++++++++++++++++++ src/leveldb/doc/log_format.md | 75 ++++ src/leveldb/doc/log_format.txt | 75 ---- src/leveldb/doc/table_format.md | 107 +++++ src/leveldb/doc/table_format.txt | 104 ----- src/leveldb/include/leveldb/db.h | 2 +- src/leveldb/include/leveldb/options.h | 12 + src/leveldb/port/port_example.h | 6 + src/leveldb/port/port_posix.h | 2 + src/leveldb/port/port_posix_sse.cc | 129 ++++++ src/leveldb/port/port_win.h | 2 + src/leveldb/table/filter_block.cc | 2 +- src/leveldb/util/crc32c.cc | 18 + src/leveldb/util/env_posix.cc | 195 +++++--- src/leveldb/util/env_posix_test.cc | 66 +++ src/leveldb/util/env_posix_test_helper.h | 28 ++ src/leveldb/util/env_test.cc | 18 +- src/leveldb/util/env_win.cc | 12 +- src/leveldb/util/options.cc | 1 + 38 files changed, 1440 insertions(+), 1155 deletions(-) delete mode 100644 src/leveldb/doc/doc.css delete mode 100644 src/leveldb/doc/impl.html create mode 100644 src/leveldb/doc/impl.md delete mode 100644 src/leveldb/doc/index.html create mode 100644 src/leveldb/doc/index.md create mode 100644 src/leveldb/doc/log_format.md delete mode 100644 src/leveldb/doc/log_format.txt create mode 100644 src/leveldb/doc/table_format.md delete mode 100644 src/leveldb/doc/table_format.txt create mode 100644 src/leveldb/port/port_posix_sse.cc create mode 100644 src/leveldb/util/env_posix_test.cc create mode 100644 src/leveldb/util/env_posix_test_helper.h diff --git a/configure.ac b/configure.ac index b24105efd037..2f7bcbe97734 100644 --- a/configure.ac +++ b/configure.ac @@ -280,6 +280,12 @@ if test "x$CXXFLAGS_overridden" = "xno"; then AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[CXXFLAGS="$CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]]) AX_CHECK_COMPILE_FLAG([-Wimplicit-fallthrough],[CXXFLAGS="$CXXFLAGS -Wno-implicit-fallthrough"],,[[$CXXFLAG_WERROR]]) + + # Check for optional instruction set support. Enabling these does _not_ imply that all code will + # be compiled with them, rather that specific objects/libs may use them after checking for runtime + # compatibility. + AX_CHECK_COMPILE_FLAG([-msse4.2],[[enable_sse42=yes; SSE42_CXXFLAGS="-msse4.2"]],,[[$CXXFLAG_WERROR]]) + fi CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS" @@ -1170,6 +1176,7 @@ AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes]) AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes]) AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes]) AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes]) +AM_CONDITIONAL([ENABLE_SSE42],[test x$enable_sse42 = xyes]) AC_DEFINE(CLIENT_VERSION_MAJOR, _CLIENT_VERSION_MAJOR, [Major version]) AC_DEFINE(CLIENT_VERSION_MINOR, _CLIENT_VERSION_MINOR, [Minor version]) @@ -1202,6 +1209,7 @@ AC_SUBST(HARDENED_CPPFLAGS) AC_SUBST(HARDENED_LDFLAGS) AC_SUBST(PIC_FLAGS) AC_SUBST(PIE_FLAGS) +AC_SUBST(SSE42_CXXFLAGS) AC_SUBST(LIBTOOL_APP_LDFLAGS) AC_SUBST(USE_UPNP) AC_SUBST(USE_QRCODE) diff --git a/src/Makefile.am b/src/Makefile.am index 57b9ccc4a839..b28c23172e76 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -536,6 +536,7 @@ dashd_LDADD = \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ + $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ $(LIBSECP256K1) diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 8153e07b7788..87876c3c2dac 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -43,6 +43,7 @@ bench_bench_dash_LDADD = \ $(LIBBITCOIN_CONSENSUS) \ $(LIBBITCOIN_CRYPTO) \ $(LIBLEVELDB) \ + $(LIBLEVELDB_SSE42) \ $(LIBMEMENV) \ $(LIBSECP256K1) \ $(LIBUNIVALUE) diff --git a/src/Makefile.leveldb.include b/src/Makefile.leveldb.include index 358f39cbef5d..ac38141f43d7 100644 --- a/src/Makefile.leveldb.include +++ b/src/Makefile.leveldb.include @@ -4,12 +4,15 @@ LIBLEVELDB_INT = leveldb/libleveldb.a LIBMEMENV_INT = leveldb/libmemenv.a +LIBLEVELDB_SSE42_INT = leveldb/libleveldb_sse42.a EXTRA_LIBRARIES += $(LIBLEVELDB_INT) EXTRA_LIBRARIES += $(LIBMEMENV_INT) +EXTRA_LIBRARIES += $(LIBLEVELDB_SSE42_INT) LIBLEVELDB += $(LIBLEVELDB_INT) LIBMEMENV += $(LIBMEMENV_INT) +LIBLEVELDB_SSE42 = $(LIBLEVELDB_SSE42_INT) LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv @@ -74,6 +77,7 @@ leveldb_libleveldb_a_SOURCES += leveldb/table/merger.h leveldb_libleveldb_a_SOURCES += leveldb/table/format.h leveldb_libleveldb_a_SOURCES += leveldb/table/iterator_wrapper.h leveldb_libleveldb_a_SOURCES += leveldb/util/crc32c.h +leveldb_libleveldb_a_SOURCES += leveldb/util/env_posix_test_helper.h leveldb_libleveldb_a_SOURCES += leveldb/util/arena.h leveldb_libleveldb_a_SOURCES += leveldb/util/random.h leveldb_libleveldb_a_SOURCES += leveldb/util/posix_logger.h @@ -135,3 +139,11 @@ leveldb_libmemenv_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS) leveldb_libmemenv_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS) leveldb_libmemenv_a_SOURCES = leveldb/helpers/memenv/memenv.cc leveldb_libmemenv_a_SOURCES += leveldb/helpers/memenv/memenv.h + +leveldb_libleveldb_sse42_a_CPPFLAGS = $(leveldb_libleveldb_a_CPPFLAGS) +leveldb_libleveldb_sse42_a_CXXFLAGS = $(leveldb_libleveldb_a_CXXFLAGS) +if ENABLE_SSE42 +leveldb_libleveldb_sse42_a_CPPFLAGS += -DLEVELDB_PLATFORM_POSIX_SSE +leveldb_libleveldb_sse42_a_CXXFLAGS += $(SSE42_CXXFLAGS) +endif +leveldb_libleveldb_sse42_a_SOURCES = leveldb/port/port_posix_sse.cc diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 9a49a45a5dfa..56a6dca1895f 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -645,7 +645,7 @@ endif if ENABLE_ZMQ qt_dash_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif -qt_dash_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ +qt_dash_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ $(BACKTRACE_LIB) $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(BLS_LIBS) qt_dash_qt_LDFLAGS = $(LDFLAGS_WRAP_EXCEPTIONS) $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 63324be321eb..4fee9ba7fc1f 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -63,7 +63,7 @@ if ENABLE_ZMQ qt_test_test_dash_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_test_test_dash_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) \ - $(LIBMEMENV) $(BACKTRACE_LIB) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ + $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BACKTRACE_LIB) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(BLS_LIBS) qt_test_test_dash_qt_LDFLAGS = $(LDFLAGS_WRAP_EXCEPTIONS) $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index c0b422858690..0a246abdab5e 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -109,8 +109,8 @@ endif test_test_dash_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES) test_test_dash_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) -test_test_dash_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \ - $(BACKTRACE_LIB) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) +test_test_dash_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) \ + $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BACKTRACE_LIB) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_dash_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) if ENABLE_WALLET test_test_dash_LDADD += $(LIBBITCOIN_WALLET) diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile index 07a5a1ead6fd..f7cc7d736c4f 100644 --- a/src/leveldb/Makefile +++ b/src/leveldb/Makefile @@ -44,6 +44,7 @@ TESTS = \ util/cache_test \ util/coding_test \ util/crc32c_test \ + util/env_posix_test \ util/env_test \ util/hash_test @@ -121,7 +122,7 @@ SHARED_MEMENVLIB = $(SHARED_OUTDIR)/libmemenv.a else # Update db.h if you change these. SHARED_VERSION_MAJOR = 1 -SHARED_VERSION_MINOR = 19 +SHARED_VERSION_MINOR = 20 SHARED_LIB1 = libleveldb.$(PLATFORM_SHARED_EXT) SHARED_LIB2 = $(SHARED_LIB1).$(SHARED_VERSION_MAJOR) SHARED_LIB3 = $(SHARED_LIB1).$(SHARED_VERSION_MAJOR).$(SHARED_VERSION_MINOR) @@ -337,6 +338,9 @@ $(STATIC_OUTDIR)/db_test:db/db_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) $(STATIC_OUTDIR)/dbformat_test:db/dbformat_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) $(CXX) $(LDFLAGS) $(CXXFLAGS) db/dbformat_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) +$(STATIC_OUTDIR)/env_posix_test:util/env_posix_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) + $(CXX) $(LDFLAGS) $(CXXFLAGS) util/env_posix_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) + $(STATIC_OUTDIR)/env_test:util/env_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) $(CXX) $(LDFLAGS) $(CXXFLAGS) util/env_test.cc $(STATIC_LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS) @@ -412,3 +416,9 @@ $(SHARED_OUTDIR)/%.o: %.cc $(SHARED_OUTDIR)/%.o: %.c $(CC) $(CFLAGS) $(PLATFORM_SHARED_CFLAGS) -c $< -o $@ + +$(STATIC_OUTDIR)/port/port_posix_sse.o: port/port_posix_sse.cc + $(CXX) $(CXXFLAGS) $(PLATFORM_SSEFLAGS) -c $< -o $@ + +$(SHARED_OUTDIR)/port/port_posix_sse.o: port/port_posix_sse.cc + $(CXX) $(CXXFLAGS) $(PLATFORM_SHARED_CFLAGS) $(PLATFORM_SSEFLAGS) -c $< -o $@ diff --git a/src/leveldb/README.md b/src/leveldb/README.md index c75b185e0e74..a010c508585e 100644 --- a/src/leveldb/README.md +++ b/src/leveldb/README.md @@ -16,7 +16,7 @@ Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com) * External activity (file system operations etc.) is relayed through a virtual interface so users can customize the operating system interactions. # Documentation - [LevelDB library documentation](https://rawgit.com/google/leveldb/master/doc/index.html) is online and bundled with the source code. + [LevelDB library documentation](https://github.com/google/leveldb/blob/master/doc/index.md) is online and bundled with the source code. # Limitations @@ -113,29 +113,30 @@ by the one or two disk seeks needed to fetch the data from disk. Write performance will be mostly unaffected by whether or not the working set fits in memory. - readrandom : 16.677 micros/op; (approximately 60,000 reads per second) - readseq : 0.476 micros/op; 232.3 MB/s - readreverse : 0.724 micros/op; 152.9 MB/s + readrandom : 16.677 micros/op; (approximately 60,000 reads per second) + readseq : 0.476 micros/op; 232.3 MB/s + readreverse : 0.724 micros/op; 152.9 MB/s LevelDB compacts its underlying storage data in the background to improve read performance. The results listed above were done immediately after a lot of random writes. The results after compactions (which are usually triggered automatically) are better. - readrandom : 11.602 micros/op; (approximately 85,000 reads per second) - readseq : 0.423 micros/op; 261.8 MB/s - readreverse : 0.663 micros/op; 166.9 MB/s + readrandom : 11.602 micros/op; (approximately 85,000 reads per second) + readseq : 0.423 micros/op; 261.8 MB/s + readreverse : 0.663 micros/op; 166.9 MB/s Some of the high cost of reads comes from repeated decompression of blocks read from disk. If we supply enough cache to the leveldb so it can hold the uncompressed blocks in memory, the read performance improves again: - readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction) - readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction) + readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction) + readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction) ## Repository contents -See doc/index.html for more explanation. See doc/impl.html for a brief overview of the implementation. +See [doc/index.md](doc/index.md) for more explanation. See +[doc/impl.md](doc/impl.md) for a brief overview of the implementation. The public interface is in include/*.h. Callers should not include or rely on the details of any other header files in this package. Those @@ -148,7 +149,7 @@ Guide to header files: * **include/options.h**: Control over the behavior of an entire database, and also control over the behavior of individual reads and writes. -* **include/comparator.h**: Abstraction for user-specified comparison function. +* **include/comparator.h**: Abstraction for user-specified comparison function. If you want just bytewise comparison of keys, you can use the default comparator, but clients can write their own comparator implementations if they want custom ordering (e.g. to handle different character encodings, etc.) @@ -165,7 +166,7 @@ length into some other byte array. * **include/status.h**: Status is returned from many of the public interfaces and is used to report success and various kinds of errors. -* **include/env.h**: +* **include/env.h**: Abstraction of the OS environment. A posix implementation of this interface is in util/env_posix.cc diff --git a/src/leveldb/build_detect_platform b/src/leveldb/build_detect_platform index d7edab1d87bb..4a9471590096 100755 --- a/src/leveldb/build_detect_platform +++ b/src/leveldb/build_detect_platform @@ -63,6 +63,7 @@ PLATFORM_SHARED_EXT="so" PLATFORM_SHARED_LDFLAGS="-shared -Wl,-soname -Wl," PLATFORM_SHARED_CFLAGS="-fPIC" PLATFORM_SHARED_VERSIONED=true +PLATFORM_SSEFLAGS= MEMCMP_FLAG= if [ "$CXX" = "g++" ]; then @@ -77,6 +78,7 @@ case "$TARGET_OS" in COMMON_FLAGS="$MEMCMP_FLAG -lpthread -DOS_LINUX -DCYGWIN" PLATFORM_LDFLAGS="-lpthread" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc ;; Darwin) PLATFORM=OS_MACOSX @@ -85,24 +87,28 @@ case "$TARGET_OS" in [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd` PLATFORM_SHARED_LDFLAGS="-dynamiclib -install_name $INSTALL_PATH/" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc ;; Linux) PLATFORM=OS_LINUX COMMON_FLAGS="$MEMCMP_FLAG -pthread -DOS_LINUX" PLATFORM_LDFLAGS="-pthread" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc ;; SunOS) PLATFORM=OS_SOLARIS COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_SOLARIS" PLATFORM_LIBS="-lpthread -lrt" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc ;; FreeBSD) PLATFORM=OS_FREEBSD COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_FREEBSD" PLATFORM_LIBS="-lpthread" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc ;; GNU/kFreeBSD) PLATFORM=OS_KFREEBSD @@ -115,24 +121,28 @@ case "$TARGET_OS" in COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_NETBSD" PLATFORM_LIBS="-lpthread -lgcc_s" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc ;; OpenBSD) PLATFORM=OS_OPENBSD COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_OPENBSD" PLATFORM_LDFLAGS="-pthread" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc ;; DragonFly) PLATFORM=OS_DRAGONFLYBSD COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_DRAGONFLYBSD" PLATFORM_LIBS="-lpthread" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc ;; OS_ANDROID_CROSSCOMPILE) PLATFORM=OS_ANDROID COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_ANDROID -DLEVELDB_PLATFORM_POSIX" PLATFORM_LDFLAGS="" # All pthread features are in the Android C library PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc CROSS_COMPILE=true ;; HP-UX) @@ -140,6 +150,7 @@ case "$TARGET_OS" in COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_HPUX" PLATFORM_LDFLAGS="-pthread" PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc # man ld: +h internal_name PLATFORM_SHARED_LDFLAGS="-shared -Wl,+h -Wl," ;; @@ -148,6 +159,7 @@ case "$TARGET_OS" in COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX" [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd` PORT_FILE=port/port_posix.cc + PORT_SSE_FILE=port/port_posix_sse.cc PLATFORM_SHARED_EXT= PLATFORM_SHARED_LDFLAGS= PLATFORM_SHARED_CFLAGS= @@ -182,7 +194,7 @@ set +f # re-enable globbing # The sources consist of the portable files, plus the platform-specific port # file. -echo "SOURCES=$PORTABLE_FILES $PORT_FILE" >> $OUTPUT +echo "SOURCES=$PORTABLE_FILES $PORT_FILE $PORT_SSE_FILE" >> $OUTPUT echo "MEMENV_SOURCES=helpers/memenv/memenv.cc" >> $OUTPUT if [ "$CROSS_COMPILE" = "true" ]; then @@ -213,6 +225,21 @@ EOF fi rm -f $CXXOUTPUT 2>/dev/null + + # Test if gcc SSE 4.2 is supported + $CXX $CXXFLAGS -x c++ - -o $CXXOUTPUT -msse4.2 2>/dev/null </dev/null +fi + +# Use the SSE 4.2 CRC32C intrinsics iff runtime checks indicate compiler supports them. +if [ -n "$PLATFORM_SSEFLAGS" ]; then + PLATFORM_SSEFLAGS="$PLATFORM_SSEFLAGS -DLEVELDB_PLATFORM_POSIX_SSE" fi PLATFORM_CCFLAGS="$PLATFORM_CCFLAGS $COMMON_FLAGS" @@ -225,6 +252,7 @@ echo "PLATFORM_LDFLAGS=$PLATFORM_LDFLAGS" >> $OUTPUT echo "PLATFORM_LIBS=$PLATFORM_LIBS" >> $OUTPUT echo "PLATFORM_CCFLAGS=$PLATFORM_CCFLAGS" >> $OUTPUT echo "PLATFORM_CXXFLAGS=$PLATFORM_CXXFLAGS" >> $OUTPUT +echo "PLATFORM_SSEFLAGS=$PLATFORM_SSEFLAGS" >> $OUTPUT echo "PLATFORM_SHARED_CFLAGS=$PLATFORM_SHARED_CFLAGS" >> $OUTPUT echo "PLATFORM_SHARED_EXT=$PLATFORM_SHARED_EXT" >> $OUTPUT echo "PLATFORM_SHARED_LDFLAGS=$PLATFORM_SHARED_LDFLAGS" >> $OUTPUT diff --git a/src/leveldb/db/db_bench.cc b/src/leveldb/db/db_bench.cc index 7a0f5e08cdd5..3ad19a512b56 100644 --- a/src/leveldb/db/db_bench.cc +++ b/src/leveldb/db/db_bench.cc @@ -84,6 +84,14 @@ static bool FLAGS_histogram = false; // (initialized to default value by "main") static int FLAGS_write_buffer_size = 0; +// Number of bytes written to each file. +// (initialized to default value by "main") +static int FLAGS_max_file_size = 0; + +// Approximate size of user data packed per block (before compression. +// (initialized to default value by "main") +static int FLAGS_block_size = 0; + // Number of bytes to use as a cache of uncompressed data. // Negative means use default settings. static int FLAGS_cache_size = -1; @@ -109,6 +117,7 @@ static const char* FLAGS_db = NULL; namespace leveldb { namespace { +leveldb::Env* g_env = NULL; // Helper for quickly generating random data. class RandomGenerator { @@ -186,7 +195,7 @@ class Stats { done_ = 0; bytes_ = 0; seconds_ = 0; - start_ = Env::Default()->NowMicros(); + start_ = g_env->NowMicros(); finish_ = start_; message_.clear(); } @@ -204,7 +213,7 @@ class Stats { } void Stop() { - finish_ = Env::Default()->NowMicros(); + finish_ = g_env->NowMicros(); seconds_ = (finish_ - start_) * 1e-6; } @@ -214,7 +223,7 @@ class Stats { void FinishedSingleOp() { if (FLAGS_histogram) { - double now = Env::Default()->NowMicros(); + double now = g_env->NowMicros(); double micros = now - last_op_finish_; hist_.Add(micros); if (micros > 20000) { @@ -404,10 +413,10 @@ class Benchmark { reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads), heap_counter_(0) { std::vector files; - Env::Default()->GetChildren(FLAGS_db, &files); + g_env->GetChildren(FLAGS_db, &files); for (size_t i = 0; i < files.size(); i++) { if (Slice(files[i]).starts_with("heap-")) { - Env::Default()->DeleteFile(std::string(FLAGS_db) + "/" + files[i]); + g_env->DeleteFile(std::string(FLAGS_db) + "/" + files[i]); } } if (!FLAGS_use_existing_db) { @@ -589,7 +598,7 @@ class Benchmark { arg[i].shared = &shared; arg[i].thread = new ThreadState(i); arg[i].thread->shared = &shared; - Env::Default()->StartThread(ThreadBody, &arg[i]); + g_env->StartThread(ThreadBody, &arg[i]); } shared.mu.Lock(); @@ -700,9 +709,12 @@ class Benchmark { void Open() { assert(db_ == NULL); Options options; + options.env = g_env; options.create_if_missing = !FLAGS_use_existing_db; options.block_cache = cache_; options.write_buffer_size = FLAGS_write_buffer_size; + options.max_file_size = FLAGS_max_file_size; + options.block_size = FLAGS_block_size; options.max_open_files = FLAGS_open_files; options.filter_policy = filter_policy_; options.reuse_logs = FLAGS_reuse_logs; @@ -925,7 +937,7 @@ class Benchmark { char fname[100]; snprintf(fname, sizeof(fname), "%s/heap-%04d", FLAGS_db, ++heap_counter_); WritableFile* file; - Status s = Env::Default()->NewWritableFile(fname, &file); + Status s = g_env->NewWritableFile(fname, &file); if (!s.ok()) { fprintf(stderr, "%s\n", s.ToString().c_str()); return; @@ -934,7 +946,7 @@ class Benchmark { delete file; if (!ok) { fprintf(stderr, "heap profiling not supported\n"); - Env::Default()->DeleteFile(fname); + g_env->DeleteFile(fname); } } }; @@ -943,6 +955,8 @@ class Benchmark { int main(int argc, char** argv) { FLAGS_write_buffer_size = leveldb::Options().write_buffer_size; + FLAGS_max_file_size = leveldb::Options().max_file_size; + FLAGS_block_size = leveldb::Options().block_size; FLAGS_open_files = leveldb::Options().max_open_files; std::string default_db_path; @@ -973,6 +987,10 @@ int main(int argc, char** argv) { FLAGS_value_size = n; } else if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) { FLAGS_write_buffer_size = n; + } else if (sscanf(argv[i], "--max_file_size=%d%c", &n, &junk) == 1) { + FLAGS_max_file_size = n; + } else if (sscanf(argv[i], "--block_size=%d%c", &n, &junk) == 1) { + FLAGS_block_size = n; } else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) { FLAGS_cache_size = n; } else if (sscanf(argv[i], "--bloom_bits=%d%c", &n, &junk) == 1) { @@ -987,9 +1005,11 @@ int main(int argc, char** argv) { } } + leveldb::g_env = leveldb::Env::Default(); + // Choose a location for the test database if none given with --db= if (FLAGS_db == NULL) { - leveldb::Env::Default()->GetTestDirectory(&default_db_path); + leveldb::g_env->GetTestDirectory(&default_db_path); default_db_path += "/dbbench"; FLAGS_db = default_db_path.c_str(); } diff --git a/src/leveldb/db/db_impl.cc b/src/leveldb/db/db_impl.cc index 60f4e66e5579..f43ad7679436 100644 --- a/src/leveldb/db/db_impl.cc +++ b/src/leveldb/db/db_impl.cc @@ -96,6 +96,7 @@ Options SanitizeOptions(const std::string& dbname, result.filter_policy = (src.filter_policy != NULL) ? ipolicy : NULL; ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000); ClipToRange(&result.write_buffer_size, 64<<10, 1<<30); + ClipToRange(&result.max_file_size, 1<<20, 1<<30); ClipToRange(&result.block_size, 1<<10, 4<<20); if (result.info_log == NULL) { // Open a log file in the same directory as the db diff --git a/src/leveldb/db/log_format.h b/src/leveldb/db/log_format.h index a8c06efe185a..356e69fca231 100644 --- a/src/leveldb/db/log_format.h +++ b/src/leveldb/db/log_format.h @@ -3,7 +3,7 @@ // found in the LICENSE file. See the AUTHORS file for names of contributors. // // Log format information shared by reader and writer. -// See ../doc/log_format.txt for more detail. +// See ../doc/log_format.md for more detail. #ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_ #define STORAGE_LEVELDB_DB_LOG_FORMAT_H_ diff --git a/src/leveldb/db/version_set.cc b/src/leveldb/db/version_set.cc index a5e0f77a6a91..b1256f90e1c2 100644 --- a/src/leveldb/db/version_set.cc +++ b/src/leveldb/db/version_set.cc @@ -20,21 +20,29 @@ namespace leveldb { -static const int kTargetFileSize = 2 * 1048576; +static int TargetFileSize(const Options* options) { + return options->max_file_size; +} // Maximum bytes of overlaps in grandparent (i.e., level+2) before we // stop building a single file in a level->level+1 compaction. -static const int64_t kMaxGrandParentOverlapBytes = 10 * kTargetFileSize; +static int64_t MaxGrandParentOverlapBytes(const Options* options) { + return 10 * TargetFileSize(options); +} // Maximum number of bytes in all compacted files. We avoid expanding // the lower level file set of a compaction if it would make the // total compaction cover more than this many bytes. -static const int64_t kExpandedCompactionByteSizeLimit = 25 * kTargetFileSize; +static int64_t ExpandedCompactionByteSizeLimit(const Options* options) { + return 25 * TargetFileSize(options); +} -static double MaxBytesForLevel(int level) { +static double MaxBytesForLevel(const Options* options, int level) { // Note: the result for level zero is not really used since we set // the level-0 compaction threshold based on number of files. - double result = 10 * 1048576.0; // Result for both level-0 and level-1 + + // Result for both level-0 and level-1 + double result = 10. * 1048576.0; while (level > 1) { result *= 10; level--; @@ -42,8 +50,9 @@ static double MaxBytesForLevel(int level) { return result; } -static uint64_t MaxFileSizeForLevel(int level) { - return kTargetFileSize; // We could vary per level to reduce number of files? +static uint64_t MaxFileSizeForLevel(const Options* options, int level) { + // We could vary per level to reduce number of files? + return TargetFileSize(options); } static int64_t TotalFileSize(const std::vector& files) { @@ -508,7 +517,7 @@ int Version::PickLevelForMemTableOutput( // Check that file does not overlap too many grandparent bytes. GetOverlappingInputs(level + 2, &start, &limit, &overlaps); const int64_t sum = TotalFileSize(overlaps); - if (sum > kMaxGrandParentOverlapBytes) { + if (sum > MaxGrandParentOverlapBytes(vset_->options_)) { break; } } @@ -1027,7 +1036,7 @@ bool VersionSet::ReuseManifest(const std::string& dscname, manifest_type != kDescriptorFile || !env_->GetFileSize(dscname, &manifest_size).ok() || // Make new compacted MANIFEST if old one is too big - manifest_size >= kTargetFileSize) { + manifest_size >= TargetFileSize(options_)) { return false; } @@ -1076,7 +1085,8 @@ void VersionSet::Finalize(Version* v) { } else { // Compute the ratio of current size to size limit. const uint64_t level_bytes = TotalFileSize(v->files_[level]); - score = static_cast(level_bytes) / MaxBytesForLevel(level); + score = + static_cast(level_bytes) / MaxBytesForLevel(options_, level); } if (score > best_score) { @@ -1290,7 +1300,7 @@ Compaction* VersionSet::PickCompaction() { level = current_->compaction_level_; assert(level >= 0); assert(level+1 < config::kNumLevels); - c = new Compaction(level); + c = new Compaction(options_, level); // Pick the first file that comes after compact_pointer_[level] for (size_t i = 0; i < current_->files_[level].size(); i++) { @@ -1307,7 +1317,7 @@ Compaction* VersionSet::PickCompaction() { } } else if (seek_compaction) { level = current_->file_to_compact_level_; - c = new Compaction(level); + c = new Compaction(options_, level); c->inputs_[0].push_back(current_->file_to_compact_); } else { return NULL; @@ -1352,7 +1362,8 @@ void VersionSet::SetupOtherInputs(Compaction* c) { const int64_t inputs1_size = TotalFileSize(c->inputs_[1]); const int64_t expanded0_size = TotalFileSize(expanded0); if (expanded0.size() > c->inputs_[0].size() && - inputs1_size + expanded0_size < kExpandedCompactionByteSizeLimit) { + inputs1_size + expanded0_size < + ExpandedCompactionByteSizeLimit(options_)) { InternalKey new_start, new_limit; GetRange(expanded0, &new_start, &new_limit); std::vector expanded1; @@ -1414,7 +1425,7 @@ Compaction* VersionSet::CompactRange( // and we must not pick one file and drop another older file if the // two files overlap. if (level > 0) { - const uint64_t limit = MaxFileSizeForLevel(level); + const uint64_t limit = MaxFileSizeForLevel(options_, level); uint64_t total = 0; for (size_t i = 0; i < inputs.size(); i++) { uint64_t s = inputs[i]->file_size; @@ -1426,7 +1437,7 @@ Compaction* VersionSet::CompactRange( } } - Compaction* c = new Compaction(level); + Compaction* c = new Compaction(options_, level); c->input_version_ = current_; c->input_version_->Ref(); c->inputs_[0] = inputs; @@ -1434,9 +1445,9 @@ Compaction* VersionSet::CompactRange( return c; } -Compaction::Compaction(int level) +Compaction::Compaction(const Options* options, int level) : level_(level), - max_output_file_size_(MaxFileSizeForLevel(level)), + max_output_file_size_(MaxFileSizeForLevel(options, level)), input_version_(NULL), grandparent_index_(0), seen_key_(false), @@ -1453,12 +1464,13 @@ Compaction::~Compaction() { } bool Compaction::IsTrivialMove() const { + const VersionSet* vset = input_version_->vset_; // Avoid a move if there is lots of overlapping grandparent data. // Otherwise, the move could create a parent file that will require // a very expensive merge later on. - return (num_input_files(0) == 1 && - num_input_files(1) == 0 && - TotalFileSize(grandparents_) <= kMaxGrandParentOverlapBytes); + return (num_input_files(0) == 1 && num_input_files(1) == 0 && + TotalFileSize(grandparents_) <= + MaxGrandParentOverlapBytes(vset->options_)); } void Compaction::AddInputDeletions(VersionEdit* edit) { @@ -1491,8 +1503,9 @@ bool Compaction::IsBaseLevelForKey(const Slice& user_key) { } bool Compaction::ShouldStopBefore(const Slice& internal_key) { + const VersionSet* vset = input_version_->vset_; // Scan to find earliest grandparent file that contains key. - const InternalKeyComparator* icmp = &input_version_->vset_->icmp_; + const InternalKeyComparator* icmp = &vset->icmp_; while (grandparent_index_ < grandparents_.size() && icmp->Compare(internal_key, grandparents_[grandparent_index_]->largest.Encode()) > 0) { @@ -1503,7 +1516,7 @@ bool Compaction::ShouldStopBefore(const Slice& internal_key) { } seen_key_ = true; - if (overlapped_bytes_ > kMaxGrandParentOverlapBytes) { + if (overlapped_bytes_ > MaxGrandParentOverlapBytes(vset->options_)) { // Too much overlap for current output; start new output overlapped_bytes_ = 0; return true; diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h index 1dec74567380..c4e7ac360b87 100644 --- a/src/leveldb/db/version_set.h +++ b/src/leveldb/db/version_set.h @@ -366,7 +366,7 @@ class Compaction { friend class Version; friend class VersionSet; - explicit Compaction(int level); + Compaction(const Options* options, int level); int level_; uint64_t max_output_file_size_; diff --git a/src/leveldb/doc/doc.css b/src/leveldb/doc/doc.css deleted file mode 100644 index 700c564e4338..000000000000 --- a/src/leveldb/doc/doc.css +++ /dev/null @@ -1,89 +0,0 @@ -body { - margin-left: 0.5in; - margin-right: 0.5in; - background: white; - color: black; -} - -h1 { - margin-left: -0.2in; - font-size: 14pt; -} -h2 { - margin-left: -0in; - font-size: 12pt; -} -h3 { - margin-left: -0in; -} -h4 { - margin-left: -0in; -} -hr { - margin-left: -0in; -} - -/* Definition lists: definition term bold */ -dt { - font-weight: bold; -} - -address { - text-align: center; -} -code,samp,var { - color: blue; -} -kbd { - color: #600000; -} -div.note p { - float: right; - width: 3in; - margin-right: 0%; - padding: 1px; - border: 2px solid #6060a0; - background-color: #fffff0; -} - -ul { - margin-top: -0em; - margin-bottom: -0em; -} - -ol { - margin-top: -0em; - margin-bottom: -0em; -} - -UL.nobullets { - list-style-type: none; - list-style-image: none; - margin-left: -1em; -} - -p { - margin: 1em 0 1em 0; - padding: 0 0 0 0; -} - -pre { - line-height: 1.3em; - padding: 0.4em 0 0.8em 0; - margin: 0 0 0 0; - border: 0 0 0 0; - color: blue; -} - -.datatable { - margin-left: auto; - margin-right: auto; - margin-top: 2em; - margin-bottom: 2em; - border: 1px solid; -} - -.datatable td,th { - padding: 0 0.5em 0 0.5em; - text-align: right; -} diff --git a/src/leveldb/doc/impl.html b/src/leveldb/doc/impl.html deleted file mode 100644 index 6a468be0955d..000000000000 --- a/src/leveldb/doc/impl.html +++ /dev/null @@ -1,213 +0,0 @@ - - - - -Leveldb file layout and compactions - - - - -

Files

- -The implementation of leveldb is similar in spirit to the -representation of a single - -Bigtable tablet (section 5.3). -However the organization of the files that make up the representation -is somewhat different and is explained below. - -

-Each database is represented by a set of files stored in a directory. -There are several different types of files as documented below: -

-

Log files

-

-A log file (*.log) stores a sequence of recent updates. Each update -is appended to the current log file. When the log file reaches a -pre-determined size (approximately 4MB by default), it is converted -to a sorted table (see below) and a new log file is created for future -updates. -

-A copy of the current log file is kept in an in-memory structure (the -memtable). This copy is consulted on every read so that read -operations reflect all logged updates. -

-

Sorted tables

-

-A sorted table (*.sst) stores a sequence of entries sorted by key. -Each entry is either a value for the key, or a deletion marker for the -key. (Deletion markers are kept around to hide obsolete values -present in older sorted tables). -

-The set of sorted tables are organized into a sequence of levels. The -sorted table generated from a log file is placed in a special young -level (also called level-0). When the number of young files exceeds a -certain threshold (currently four), all of the young files are merged -together with all of the overlapping level-1 files to produce a -sequence of new level-1 files (we create a new level-1 file for every -2MB of data.) -

-Files in the young level may contain overlapping keys. However files -in other levels have distinct non-overlapping key ranges. Consider -level number L where L >= 1. When the combined size of files in -level-L exceeds (10^L) MB (i.e., 10MB for level-1, 100MB for level-2, -...), one file in level-L, and all of the overlapping files in -level-(L+1) are merged to form a set of new files for level-(L+1). -These merges have the effect of gradually migrating new updates from -the young level to the largest level using only bulk reads and writes -(i.e., minimizing expensive seeks). - -

Manifest

-

-A MANIFEST file lists the set of sorted tables that make up each -level, the corresponding key ranges, and other important metadata. -A new MANIFEST file (with a new number embedded in the file name) -is created whenever the database is reopened. The MANIFEST file is -formatted as a log, and changes made to the serving state (as files -are added or removed) are appended to this log. -

-

Current

-

-CURRENT is a simple text file that contains the name of the latest -MANIFEST file. -

-

Info logs

-

-Informational messages are printed to files named LOG and LOG.old. -

-

Others

-

-Other files used for miscellaneous purposes may also be present -(LOCK, *.dbtmp). - -

Level 0

-When the log file grows above a certain size (1MB by default): -
    -
  • Create a brand new memtable and log file and direct future updates here -
  • In the background: -
      -
    • Write the contents of the previous memtable to an sstable -
    • Discard the memtable -
    • Delete the old log file and the old memtable -
    • Add the new sstable to the young (level-0) level. -
    -
- -

Compactions

- -

-When the size of level L exceeds its limit, we compact it in a -background thread. The compaction picks a file from level L and all -overlapping files from the next level L+1. Note that if a level-L -file overlaps only part of a level-(L+1) file, the entire file at -level-(L+1) is used as an input to the compaction and will be -discarded after the compaction. Aside: because level-0 is special -(files in it may overlap each other), we treat compactions from -level-0 to level-1 specially: a level-0 compaction may pick more than -one level-0 file in case some of these files overlap each other. - -

-A compaction merges the contents of the picked files to produce a -sequence of level-(L+1) files. We switch to producing a new -level-(L+1) file after the current output file has reached the target -file size (2MB). We also switch to a new output file when the key -range of the current output file has grown enough to overlap more than -ten level-(L+2) files. This last rule ensures that a later compaction -of a level-(L+1) file will not pick up too much data from level-(L+2). - -

-The old files are discarded and the new files are added to the serving -state. - -

-Compactions for a particular level rotate through the key space. In -more detail, for each level L, we remember the ending key of the last -compaction at level L. The next compaction for level L will pick the -first file that starts after this key (wrapping around to the -beginning of the key space if there is no such file). - -

-Compactions drop overwritten values. They also drop deletion markers -if there are no higher numbered levels that contain a file whose range -overlaps the current key. - -

Timing

- -Level-0 compactions will read up to four 1MB files from level-0, and -at worst all the level-1 files (10MB). I.e., we will read 14MB and -write 14MB. - -

-Other than the special level-0 compactions, we will pick one 2MB file -from level L. In the worst case, this will overlap ~ 12 files from -level L+1 (10 because level-(L+1) is ten times the size of level-L, -and another two at the boundaries since the file ranges at level-L -will usually not be aligned with the file ranges at level-L+1). The -compaction will therefore read 26MB and write 26MB. Assuming a disk -IO rate of 100MB/s (ballpark range for modern drives), the worst -compaction cost will be approximately 0.5 second. - -

-If we throttle the background writing to something small, say 10% of -the full 100MB/s speed, a compaction may take up to 5 seconds. If the -user is writing at 10MB/s, we might build up lots of level-0 files -(~50 to hold the 5*10MB). This may significantly increase the cost of -reads due to the overhead of merging more files together on every -read. - -

-Solution 1: To reduce this problem, we might want to increase the log -switching threshold when the number of level-0 files is large. Though -the downside is that the larger this threshold, the more memory we will -need to hold the corresponding memtable. - -

-Solution 2: We might want to decrease write rate artificially when the -number of level-0 files goes up. - -

-Solution 3: We work on reducing the cost of very wide merges. -Perhaps most of the level-0 files will have their blocks sitting -uncompressed in the cache and we will only need to worry about the -O(N) complexity in the merging iterator. - -

Number of files

- -Instead of always making 2MB files, we could make larger files for -larger levels to reduce the total file count, though at the expense of -more bursty compactions. Alternatively, we could shard the set of -files into multiple directories. - -

-An experiment on an ext3 filesystem on Feb 04, 2011 shows -the following timings to do 100K file opens in directories with -varying number of files: - - - - - -
Files in directoryMicroseconds to open a file
10009
1000010
10000016
-So maybe even the sharding is not necessary on modern filesystems? - -

Recovery

- -
    -
  • Read CURRENT to find name of the latest committed MANIFEST -
  • Read the named MANIFEST file -
  • Clean up stale files -
  • We could open all sstables here, but it is probably better to be lazy... -
  • Convert log chunk to a new level-0 sstable -
  • Start directing new writes to a new log file with recovered sequence# -
- -

Garbage collection of files

- -DeleteObsoleteFiles() is called at the end of every -compaction and at the end of recovery. It finds the names of all -files in the database. It deletes all log files that are not the -current log file. It deletes all table files that are not referenced -from some level and are not the output of an active compaction. - - - diff --git a/src/leveldb/doc/impl.md b/src/leveldb/doc/impl.md new file mode 100644 index 000000000000..4b13f2a6ba73 --- /dev/null +++ b/src/leveldb/doc/impl.md @@ -0,0 +1,170 @@ +## Files + +The implementation of leveldb is similar in spirit to the representation of a +single [Bigtable tablet (section 5.3)](http://research.google.com/archive/bigtable.html). +However the organization of the files that make up the representation is +somewhat different and is explained below. + +Each database is represented by a set of files stored in a directory. There are +several different types of files as documented below: + +### Log files + +A log file (*.log) stores a sequence of recent updates. Each update is appended +to the current log file. When the log file reaches a pre-determined size +(approximately 4MB by default), it is converted to a sorted table (see below) +and a new log file is created for future updates. + +A copy of the current log file is kept in an in-memory structure (the +`memtable`). This copy is consulted on every read so that read operations +reflect all logged updates. + +## Sorted tables + +A sorted table (*.ldb) stores a sequence of entries sorted by key. Each entry is +either a value for the key, or a deletion marker for the key. (Deletion markers +are kept around to hide obsolete values present in older sorted tables). + +The set of sorted tables are organized into a sequence of levels. The sorted +table generated from a log file is placed in a special **young** level (also +called level-0). When the number of young files exceeds a certain threshold +(currently four), all of the young files are merged together with all of the +overlapping level-1 files to produce a sequence of new level-1 files (we create +a new level-1 file for every 2MB of data.) + +Files in the young level may contain overlapping keys. However files in other +levels have distinct non-overlapping key ranges. Consider level number L where +L >= 1. When the combined size of files in level-L exceeds (10^L) MB (i.e., 10MB +for level-1, 100MB for level-2, ...), one file in level-L, and all of the +overlapping files in level-(L+1) are merged to form a set of new files for +level-(L+1). These merges have the effect of gradually migrating new updates +from the young level to the largest level using only bulk reads and writes +(i.e., minimizing expensive seeks). + +### Manifest + +A MANIFEST file lists the set of sorted tables that make up each level, the +corresponding key ranges, and other important metadata. A new MANIFEST file +(with a new number embedded in the file name) is created whenever the database +is reopened. The MANIFEST file is formatted as a log, and changes made to the +serving state (as files are added or removed) are appended to this log. + +### Current + +CURRENT is a simple text file that contains the name of the latest MANIFEST +file. + +### Info logs + +Informational messages are printed to files named LOG and LOG.old. + +### Others + +Other files used for miscellaneous purposes may also be present (LOCK, *.dbtmp). + +## Level 0 + +When the log file grows above a certain size (1MB by default): +Create a brand new memtable and log file and direct future updates here +In the background: +Write the contents of the previous memtable to an sstable +Discard the memtable +Delete the old log file and the old memtable +Add the new sstable to the young (level-0) level. + +## Compactions + +When the size of level L exceeds its limit, we compact it in a background +thread. The compaction picks a file from level L and all overlapping files from +the next level L+1. Note that if a level-L file overlaps only part of a +level-(L+1) file, the entire file at level-(L+1) is used as an input to the +compaction and will be discarded after the compaction. Aside: because level-0 +is special (files in it may overlap each other), we treat compactions from +level-0 to level-1 specially: a level-0 compaction may pick more than one +level-0 file in case some of these files overlap each other. + +A compaction merges the contents of the picked files to produce a sequence of +level-(L+1) files. We switch to producing a new level-(L+1) file after the +current output file has reached the target file size (2MB). We also switch to a +new output file when the key range of the current output file has grown enough +to overlap more than ten level-(L+2) files. This last rule ensures that a later +compaction of a level-(L+1) file will not pick up too much data from +level-(L+2). + +The old files are discarded and the new files are added to the serving state. + +Compactions for a particular level rotate through the key space. In more detail, +for each level L, we remember the ending key of the last compaction at level L. +The next compaction for level L will pick the first file that starts after this +key (wrapping around to the beginning of the key space if there is no such +file). + +Compactions drop overwritten values. They also drop deletion markers if there +are no higher numbered levels that contain a file whose range overlaps the +current key. + +### Timing + +Level-0 compactions will read up to four 1MB files from level-0, and at worst +all the level-1 files (10MB). I.e., we will read 14MB and write 14MB. + +Other than the special level-0 compactions, we will pick one 2MB file from level +L. In the worst case, this will overlap ~ 12 files from level L+1 (10 because +level-(L+1) is ten times the size of level-L, and another two at the boundaries +since the file ranges at level-L will usually not be aligned with the file +ranges at level-L+1). The compaction will therefore read 26MB and write 26MB. +Assuming a disk IO rate of 100MB/s (ballpark range for modern drives), the worst +compaction cost will be approximately 0.5 second. + +If we throttle the background writing to something small, say 10% of the full +100MB/s speed, a compaction may take up to 5 seconds. If the user is writing at +10MB/s, we might build up lots of level-0 files (~50 to hold the 5*10MB). This +may significantly increase the cost of reads due to the overhead of merging more +files together on every read. + +Solution 1: To reduce this problem, we might want to increase the log switching +threshold when the number of level-0 files is large. Though the downside is that +the larger this threshold, the more memory we will need to hold the +corresponding memtable. + +Solution 2: We might want to decrease write rate artificially when the number of +level-0 files goes up. + +Solution 3: We work on reducing the cost of very wide merges. Perhaps most of +the level-0 files will have their blocks sitting uncompressed in the cache and +we will only need to worry about the O(N) complexity in the merging iterator. + +### Number of files + +Instead of always making 2MB files, we could make larger files for larger levels +to reduce the total file count, though at the expense of more bursty +compactions. Alternatively, we could shard the set of files into multiple +directories. + +An experiment on an ext3 filesystem on Feb 04, 2011 shows the following timings +to do 100K file opens in directories with varying number of files: + + +| Files in directory | Microseconds to open a file | +|-------------------:|----------------------------:| +| 1000 | 9 | +| 10000 | 10 | +| 100000 | 16 | + +So maybe even the sharding is not necessary on modern filesystems? + +## Recovery + +* Read CURRENT to find name of the latest committed MANIFEST +* Read the named MANIFEST file +* Clean up stale files +* We could open all sstables here, but it is probably better to be lazy... +* Convert log chunk to a new level-0 sstable +* Start directing new writes to a new log file with recovered sequence# + +## Garbage collection of files + +`DeleteObsoleteFiles()` is called at the end of every compaction and at the end +of recovery. It finds the names of all files in the database. It deletes all log +files that are not the current log file. It deletes all table files that are not +referenced from some level and are not the output of an active compaction. diff --git a/src/leveldb/doc/index.html b/src/leveldb/doc/index.html deleted file mode 100644 index 2155192581e7..000000000000 --- a/src/leveldb/doc/index.html +++ /dev/null @@ -1,549 +0,0 @@ - - - - -Leveldb - - - -

Leveldb

-
Jeff Dean, Sanjay Ghemawat
-

-The leveldb library provides a persistent key value store. Keys and -values are arbitrary byte arrays. The keys are ordered within the key -value store according to a user-specified comparator function. - -

-

Opening A Database

-

-A leveldb database has a name which corresponds to a file system -directory. All of the contents of database are stored in this -directory. The following example shows how to open a database, -creating it if necessary: -

-

-  #include <cassert>
-  #include "leveldb/db.h"
-
-  leveldb::DB* db;
-  leveldb::Options options;
-  options.create_if_missing = true;
-  leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
-  assert(status.ok());
-  ...
-
-If you want to raise an error if the database already exists, add -the following line before the leveldb::DB::Open call: -
-  options.error_if_exists = true;
-
-

Status

-

-You may have noticed the leveldb::Status type above. Values of this -type are returned by most functions in leveldb that may encounter an -error. You can check if such a result is ok, and also print an -associated error message: -

-

-   leveldb::Status s = ...;
-   if (!s.ok()) cerr << s.ToString() << endl;
-
-

Closing A Database

-

-When you are done with a database, just delete the database object. -Example: -

-

-  ... open the db as described above ...
-  ... do something with db ...
-  delete db;
-
-

Reads And Writes

-

-The database provides Put, Delete, and Get methods to -modify/query the database. For example, the following code -moves the value stored under key1 to key2. -

-  std::string value;
-  leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
-  if (s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value);
-  if (s.ok()) s = db->Delete(leveldb::WriteOptions(), key1);
-
- -

Atomic Updates

-

-Note that if the process dies after the Put of key2 but before the -delete of key1, the same value may be left stored under multiple keys. -Such problems can be avoided by using the WriteBatch class to -atomically apply a set of updates: -

-

-  #include "leveldb/write_batch.h"
-  ...
-  std::string value;
-  leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value);
-  if (s.ok()) {
-    leveldb::WriteBatch batch;
-    batch.Delete(key1);
-    batch.Put(key2, value);
-    s = db->Write(leveldb::WriteOptions(), &batch);
-  }
-
-The WriteBatch holds a sequence of edits to be made to the database, -and these edits within the batch are applied in order. Note that we -called Delete before Put so that if key1 is identical to key2, -we do not end up erroneously dropping the value entirely. -

-Apart from its atomicity benefits, WriteBatch may also be used to -speed up bulk updates by placing lots of individual mutations into the -same batch. - -

Synchronous Writes

-By default, each write to leveldb is asynchronous: it -returns after pushing the write from the process into the operating -system. The transfer from operating system memory to the underlying -persistent storage happens asynchronously. The sync flag -can be turned on for a particular write to make the write operation -not return until the data being written has been pushed all the way to -persistent storage. (On Posix systems, this is implemented by calling -either fsync(...) or fdatasync(...) or -msync(..., MS_SYNC) before the write operation returns.) -
-  leveldb::WriteOptions write_options;
-  write_options.sync = true;
-  db->Put(write_options, ...);
-
-Asynchronous writes are often more than a thousand times as fast as -synchronous writes. The downside of asynchronous writes is that a -crash of the machine may cause the last few updates to be lost. Note -that a crash of just the writing process (i.e., not a reboot) will not -cause any loss since even when sync is false, an update -is pushed from the process memory into the operating system before it -is considered done. - -

-Asynchronous writes can often be used safely. For example, when -loading a large amount of data into the database you can handle lost -updates by restarting the bulk load after a crash. A hybrid scheme is -also possible where every Nth write is synchronous, and in the event -of a crash, the bulk load is restarted just after the last synchronous -write finished by the previous run. (The synchronous write can update -a marker that describes where to restart on a crash.) - -

-WriteBatch provides an alternative to asynchronous writes. -Multiple updates may be placed in the same WriteBatch and -applied together using a synchronous write (i.e., -write_options.sync is set to true). The extra cost of -the synchronous write will be amortized across all of the writes in -the batch. - -

-

Concurrency

-

-A database may only be opened by one process at a time. -The leveldb implementation acquires a lock from the -operating system to prevent misuse. Within a single process, the -same leveldb::DB object may be safely shared by multiple -concurrent threads. I.e., different threads may write into or fetch -iterators or call Get on the same database without any -external synchronization (the leveldb implementation will -automatically do the required synchronization). However other objects -(like Iterator and WriteBatch) may require external synchronization. -If two threads share such an object, they must protect access to it -using their own locking protocol. More details are available in -the public header files. -

-

Iteration

-

-The following example demonstrates how to print all key,value pairs -in a database. -

-

-  leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions());
-  for (it->SeekToFirst(); it->Valid(); it->Next()) {
-    cout << it->key().ToString() << ": "  << it->value().ToString() << endl;
-  }
-  assert(it->status().ok());  // Check for any errors found during the scan
-  delete it;
-
-The following variation shows how to process just the keys in the -range [start,limit): -

-

-  for (it->Seek(start);
-       it->Valid() && it->key().ToString() < limit;
-       it->Next()) {
-    ...
-  }
-
-You can also process entries in reverse order. (Caveat: reverse -iteration may be somewhat slower than forward iteration.) -

-

-  for (it->SeekToLast(); it->Valid(); it->Prev()) {
-    ...
-  }
-
-

Snapshots

-

-Snapshots provide consistent read-only views over the entire state of -the key-value store. ReadOptions::snapshot may be non-NULL to indicate -that a read should operate on a particular version of the DB state. -If ReadOptions::snapshot is NULL, the read will operate on an -implicit snapshot of the current state. -

-Snapshots are created by the DB::GetSnapshot() method: -

-

-  leveldb::ReadOptions options;
-  options.snapshot = db->GetSnapshot();
-  ... apply some updates to db ...
-  leveldb::Iterator* iter = db->NewIterator(options);
-  ... read using iter to view the state when the snapshot was created ...
-  delete iter;
-  db->ReleaseSnapshot(options.snapshot);
-
-Note that when a snapshot is no longer needed, it should be released -using the DB::ReleaseSnapshot interface. This allows the -implementation to get rid of state that was being maintained just to -support reading as of that snapshot. -

Slice

-

-The return value of the it->key() and it->value() calls above -are instances of the leveldb::Slice type. Slice is a simple -structure that contains a length and a pointer to an external byte -array. Returning a Slice is a cheaper alternative to returning a -std::string since we do not need to copy potentially large keys and -values. In addition, leveldb methods do not return null-terminated -C-style strings since leveldb keys and values are allowed to -contain '\0' bytes. -

-C++ strings and null-terminated C-style strings can be easily converted -to a Slice: -

-

-   leveldb::Slice s1 = "hello";
-
-   std::string str("world");
-   leveldb::Slice s2 = str;
-
-A Slice can be easily converted back to a C++ string: -
-   std::string str = s1.ToString();
-   assert(str == std::string("hello"));
-
-Be careful when using Slices since it is up to the caller to ensure that -the external byte array into which the Slice points remains live while -the Slice is in use. For example, the following is buggy: -

-

-   leveldb::Slice slice;
-   if (...) {
-     std::string str = ...;
-     slice = str;
-   }
-   Use(slice);
-
-When the if statement goes out of scope, str will be destroyed and the -backing storage for slice will disappear. -

-

Comparators

-

-The preceding examples used the default ordering function for key, -which orders bytes lexicographically. You can however supply a custom -comparator when opening a database. For example, suppose each -database key consists of two numbers and we should sort by the first -number, breaking ties by the second number. First, define a proper -subclass of leveldb::Comparator that expresses these rules: -

-

-  class TwoPartComparator : public leveldb::Comparator {
-   public:
-    // Three-way comparison function:
-    //   if a < b: negative result
-    //   if a > b: positive result
-    //   else: zero result
-    int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const {
-      int a1, a2, b1, b2;
-      ParseKey(a, &a1, &a2);
-      ParseKey(b, &b1, &b2);
-      if (a1 < b1) return -1;
-      if (a1 > b1) return +1;
-      if (a2 < b2) return -1;
-      if (a2 > b2) return +1;
-      return 0;
-    }
-
-    // Ignore the following methods for now:
-    const char* Name() const { return "TwoPartComparator"; }
-    void FindShortestSeparator(std::string*, const leveldb::Slice&) const { }
-    void FindShortSuccessor(std::string*) const { }
-  };
-
-Now create a database using this custom comparator: -

-

-  TwoPartComparator cmp;
-  leveldb::DB* db;
-  leveldb::Options options;
-  options.create_if_missing = true;
-  options.comparator = &cmp;
-  leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db);
-  ...
-
-

Backwards compatibility

-

-The result of the comparator's Name method is attached to the -database when it is created, and is checked on every subsequent -database open. If the name changes, the leveldb::DB::Open call will -fail. Therefore, change the name if and only if the new key format -and comparison function are incompatible with existing databases, and -it is ok to discard the contents of all existing databases. -

-You can however still gradually evolve your key format over time with -a little bit of pre-planning. For example, you could store a version -number at the end of each key (one byte should suffice for most uses). -When you wish to switch to a new key format (e.g., adding an optional -third part to the keys processed by TwoPartComparator), -(a) keep the same comparator name (b) increment the version number -for new keys (c) change the comparator function so it uses the -version numbers found in the keys to decide how to interpret them. -

-

Performance

-

-Performance can be tuned by changing the default values of the -types defined in include/leveldb/options.h. - -

-

Block size

-

-leveldb groups adjacent keys together into the same block and such a -block is the unit of transfer to and from persistent storage. The -default block size is approximately 4096 uncompressed bytes. -Applications that mostly do bulk scans over the contents of the -database may wish to increase this size. Applications that do a lot -of point reads of small values may wish to switch to a smaller block -size if performance measurements indicate an improvement. There isn't -much benefit in using blocks smaller than one kilobyte, or larger than -a few megabytes. Also note that compression will be more effective -with larger block sizes. -

-

Compression

-

-Each block is individually compressed before being written to -persistent storage. Compression is on by default since the default -compression method is very fast, and is automatically disabled for -uncompressible data. In rare cases, applications may want to disable -compression entirely, but should only do so if benchmarks show a -performance improvement: -

-

-  leveldb::Options options;
-  options.compression = leveldb::kNoCompression;
-  ... leveldb::DB::Open(options, name, ...) ....
-
-

Cache

-

-The contents of the database are stored in a set of files in the -filesystem and each file stores a sequence of compressed blocks. If -options.cache is non-NULL, it is used to cache frequently used -uncompressed block contents. -

-

-  #include "leveldb/cache.h"
-
-  leveldb::Options options;
-  options.cache = leveldb::NewLRUCache(100 * 1048576);  // 100MB cache
-  leveldb::DB* db;
-  leveldb::DB::Open(options, name, &db);
-  ... use the db ...
-  delete db
-  delete options.cache;
-
-Note that the cache holds uncompressed data, and therefore it should -be sized according to application level data sizes, without any -reduction from compression. (Caching of compressed blocks is left to -the operating system buffer cache, or any custom Env -implementation provided by the client.) -

-When performing a bulk read, the application may wish to disable -caching so that the data processed by the bulk read does not end up -displacing most of the cached contents. A per-iterator option can be -used to achieve this: -

-

-  leveldb::ReadOptions options;
-  options.fill_cache = false;
-  leveldb::Iterator* it = db->NewIterator(options);
-  for (it->SeekToFirst(); it->Valid(); it->Next()) {
-    ...
-  }
-
-

Key Layout

-

-Note that the unit of disk transfer and caching is a block. Adjacent -keys (according to the database sort order) will usually be placed in -the same block. Therefore the application can improve its performance -by placing keys that are accessed together near each other and placing -infrequently used keys in a separate region of the key space. -

-For example, suppose we are implementing a simple file system on top -of leveldb. The types of entries we might wish to store are: -

-

-   filename -> permission-bits, length, list of file_block_ids
-   file_block_id -> data
-
-We might want to prefix filename keys with one letter (say '/') and the -file_block_id keys with a different letter (say '0') so that scans -over just the metadata do not force us to fetch and cache bulky file -contents. -

-

Filters

-

-Because of the way leveldb data is organized on disk, -a single Get() call may involve multiple reads from disk. -The optional FilterPolicy mechanism can be used to reduce -the number of disk reads substantially. -

-   leveldb::Options options;
-   options.filter_policy = NewBloomFilterPolicy(10);
-   leveldb::DB* db;
-   leveldb::DB::Open(options, "/tmp/testdb", &db);
-   ... use the database ...
-   delete db;
-   delete options.filter_policy;
-
-The preceding code associates a -Bloom filter -based filtering policy with the database. Bloom filter based -filtering relies on keeping some number of bits of data in memory per -key (in this case 10 bits per key since that is the argument we passed -to NewBloomFilterPolicy). This filter will reduce the number of unnecessary -disk reads needed for Get() calls by a factor of -approximately a 100. Increasing the bits per key will lead to a -larger reduction at the cost of more memory usage. We recommend that -applications whose working set does not fit in memory and that do a -lot of random reads set a filter policy. -

-If you are using a custom comparator, you should ensure that the filter -policy you are using is compatible with your comparator. For example, -consider a comparator that ignores trailing spaces when comparing keys. -NewBloomFilterPolicy must not be used with such a comparator. -Instead, the application should provide a custom filter policy that -also ignores trailing spaces. For example: -

-  class CustomFilterPolicy : public leveldb::FilterPolicy {
-   private:
-    FilterPolicy* builtin_policy_;
-   public:
-    CustomFilterPolicy() : builtin_policy_(NewBloomFilterPolicy(10)) { }
-    ~CustomFilterPolicy() { delete builtin_policy_; }
-
-    const char* Name() const { return "IgnoreTrailingSpacesFilter"; }
-
-    void CreateFilter(const Slice* keys, int n, std::string* dst) const {
-      // Use builtin bloom filter code after removing trailing spaces
-      std::vector<Slice> trimmed(n);
-      for (int i = 0; i < n; i++) {
-        trimmed[i] = RemoveTrailingSpaces(keys[i]);
-      }
-      return builtin_policy_->CreateFilter(&trimmed[i], n, dst);
-    }
-
-    bool KeyMayMatch(const Slice& key, const Slice& filter) const {
-      // Use builtin bloom filter code after removing trailing spaces
-      return builtin_policy_->KeyMayMatch(RemoveTrailingSpaces(key), filter);
-    }
-  };
-
-

-Advanced applications may provide a filter policy that does not use -a bloom filter but uses some other mechanism for summarizing a set -of keys. See leveldb/filter_policy.h for detail. -

-

Checksums

-

-leveldb associates checksums with all data it stores in the file system. -There are two separate controls provided over how aggressively these -checksums are verified: -

-

    -
  • ReadOptions::verify_checksums may be set to true to force - checksum verification of all data that is read from the file system on - behalf of a particular read. By default, no such verification is - done. -

    -

  • Options::paranoid_checks may be set to true before opening a - database to make the database implementation raise an error as soon as - it detects an internal corruption. Depending on which portion of the - database has been corrupted, the error may be raised when the database - is opened, or later by another database operation. By default, - paranoid checking is off so that the database can be used even if - parts of its persistent storage have been corrupted. -

    - If a database is corrupted (perhaps it cannot be opened when - paranoid checking is turned on), the leveldb::RepairDB function - may be used to recover as much of the data as possible -

    -

-

Approximate Sizes

-

-The GetApproximateSizes method can used to get the approximate -number of bytes of file system space used by one or more key ranges. -

-

-   leveldb::Range ranges[2];
-   ranges[0] = leveldb::Range("a", "c");
-   ranges[1] = leveldb::Range("x", "z");
-   uint64_t sizes[2];
-   leveldb::Status s = db->GetApproximateSizes(ranges, 2, sizes);
-
-The preceding call will set sizes[0] to the approximate number of -bytes of file system space used by the key range [a..c) and -sizes[1] to the approximate number of bytes used by the key range -[x..z). -

-

Environment

-

-All file operations (and other operating system calls) issued by the -leveldb implementation are routed through a leveldb::Env object. -Sophisticated clients may wish to provide their own Env -implementation to get better control. For example, an application may -introduce artificial delays in the file IO paths to limit the impact -of leveldb on other activities in the system. -

-

-  class SlowEnv : public leveldb::Env {
-    .. implementation of the Env interface ...
-  };
-
-  SlowEnv env;
-  leveldb::Options options;
-  options.env = &env;
-  Status s = leveldb::DB::Open(options, ...);
-
-

Porting

-

-leveldb may be ported to a new platform by providing platform -specific implementations of the types/methods/functions exported by -leveldb/port/port.h. See leveldb/port/port_example.h for more -details. -

-In addition, the new platform may need a new default leveldb::Env -implementation. See leveldb/util/env_posix.h for an example. - -

Other Information

- -

-Details about the leveldb implementation may be found in -the following documents: -

- - - diff --git a/src/leveldb/doc/index.md b/src/leveldb/doc/index.md new file mode 100644 index 000000000000..be8569692bb0 --- /dev/null +++ b/src/leveldb/doc/index.md @@ -0,0 +1,523 @@ +leveldb +======= + +_Jeff Dean, Sanjay Ghemawat_ + +The leveldb library provides a persistent key value store. Keys and values are +arbitrary byte arrays. The keys are ordered within the key value store +according to a user-specified comparator function. + +## Opening A Database + +A leveldb database has a name which corresponds to a file system directory. All +of the contents of database are stored in this directory. The following example +shows how to open a database, creating it if necessary: + +```c++ +#include +#include "leveldb/db.h" + +leveldb::DB* db; +leveldb::Options options; +options.create_if_missing = true; +leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db); +assert(status.ok()); +... +``` + +If you want to raise an error if the database already exists, add the following +line before the `leveldb::DB::Open` call: + +```c++ +options.error_if_exists = true; +``` + +## Status + +You may have noticed the `leveldb::Status` type above. Values of this type are +returned by most functions in leveldb that may encounter an error. You can check +if such a result is ok, and also print an associated error message: + +```c++ +leveldb::Status s = ...; +if (!s.ok()) cerr << s.ToString() << endl; +``` + +## Closing A Database + +When you are done with a database, just delete the database object. Example: + +```c++ +... open the db as described above ... +... do something with db ... +delete db; +``` + +## Reads And Writes + +The database provides Put, Delete, and Get methods to modify/query the database. +For example, the following code moves the value stored under key1 to key2. + +```c++ +std::string value; +leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value); +if (s.ok()) s = db->Put(leveldb::WriteOptions(), key2, value); +if (s.ok()) s = db->Delete(leveldb::WriteOptions(), key1); +``` + +## Atomic Updates + +Note that if the process dies after the Put of key2 but before the delete of +key1, the same value may be left stored under multiple keys. Such problems can +be avoided by using the `WriteBatch` class to atomically apply a set of updates: + +```c++ +#include "leveldb/write_batch.h" +... +std::string value; +leveldb::Status s = db->Get(leveldb::ReadOptions(), key1, &value); +if (s.ok()) { + leveldb::WriteBatch batch; + batch.Delete(key1); + batch.Put(key2, value); + s = db->Write(leveldb::WriteOptions(), &batch); +} +``` + +The `WriteBatch` holds a sequence of edits to be made to the database, and these +edits within the batch are applied in order. Note that we called Delete before +Put so that if key1 is identical to key2, we do not end up erroneously dropping +the value entirely. + +Apart from its atomicity benefits, `WriteBatch` may also be used to speed up +bulk updates by placing lots of individual mutations into the same batch. + +## Synchronous Writes + +By default, each write to leveldb is asynchronous: it returns after pushing the +write from the process into the operating system. The transfer from operating +system memory to the underlying persistent storage happens asynchronously. The +sync flag can be turned on for a particular write to make the write operation +not return until the data being written has been pushed all the way to +persistent storage. (On Posix systems, this is implemented by calling either +`fsync(...)` or `fdatasync(...)` or `msync(..., MS_SYNC)` before the write +operation returns.) + +```c++ +leveldb::WriteOptions write_options; +write_options.sync = true; +db->Put(write_options, ...); +``` + +Asynchronous writes are often more than a thousand times as fast as synchronous +writes. The downside of asynchronous writes is that a crash of the machine may +cause the last few updates to be lost. Note that a crash of just the writing +process (i.e., not a reboot) will not cause any loss since even when sync is +false, an update is pushed from the process memory into the operating system +before it is considered done. + +Asynchronous writes can often be used safely. For example, when loading a large +amount of data into the database you can handle lost updates by restarting the +bulk load after a crash. A hybrid scheme is also possible where every Nth write +is synchronous, and in the event of a crash, the bulk load is restarted just +after the last synchronous write finished by the previous run. (The synchronous +write can update a marker that describes where to restart on a crash.) + +`WriteBatch` provides an alternative to asynchronous writes. Multiple updates +may be placed in the same WriteBatch and applied together using a synchronous +write (i.e., `write_options.sync` is set to true). The extra cost of the +synchronous write will be amortized across all of the writes in the batch. + +## Concurrency + +A database may only be opened by one process at a time. The leveldb +implementation acquires a lock from the operating system to prevent misuse. +Within a single process, the same `leveldb::DB` object may be safely shared by +multiple concurrent threads. I.e., different threads may write into or fetch +iterators or call Get on the same database without any external synchronization +(the leveldb implementation will automatically do the required synchronization). +However other objects (like Iterator and `WriteBatch`) may require external +synchronization. If two threads share such an object, they must protect access +to it using their own locking protocol. More details are available in the public +header files. + +## Iteration + +The following example demonstrates how to print all key,value pairs in a +database. + +```c++ +leveldb::Iterator* it = db->NewIterator(leveldb::ReadOptions()); +for (it->SeekToFirst(); it->Valid(); it->Next()) { + cout << it->key().ToString() << ": " << it->value().ToString() << endl; +} +assert(it->status().ok()); // Check for any errors found during the scan +delete it; +``` + +The following variation shows how to process just the keys in the range +[start,limit): + +```c++ +for (it->Seek(start); + it->Valid() && it->key().ToString() < limit; + it->Next()) { + ... +} +``` + +You can also process entries in reverse order. (Caveat: reverse iteration may be +somewhat slower than forward iteration.) + +```c++ +for (it->SeekToLast(); it->Valid(); it->Prev()) { + ... +} +``` + +## Snapshots + +Snapshots provide consistent read-only views over the entire state of the +key-value store. `ReadOptions::snapshot` may be non-NULL to indicate that a +read should operate on a particular version of the DB state. If +`ReadOptions::snapshot` is NULL, the read will operate on an implicit snapshot +of the current state. + +Snapshots are created by the `DB::GetSnapshot()` method: + +```c++ +leveldb::ReadOptions options; +options.snapshot = db->GetSnapshot(); +... apply some updates to db ... +leveldb::Iterator* iter = db->NewIterator(options); +... read using iter to view the state when the snapshot was created ... +delete iter; +db->ReleaseSnapshot(options.snapshot); +``` + +Note that when a snapshot is no longer needed, it should be released using the +`DB::ReleaseSnapshot` interface. This allows the implementation to get rid of +state that was being maintained just to support reading as of that snapshot. + +## Slice + +The return value of the `it->key()` and `it->value()` calls above are instances +of the `leveldb::Slice` type. Slice is a simple structure that contains a length +and a pointer to an external byte array. Returning a Slice is a cheaper +alternative to returning a `std::string` since we do not need to copy +potentially large keys and values. In addition, leveldb methods do not return +null-terminated C-style strings since leveldb keys and values are allowed to +contain `'\0'` bytes. + +C++ strings and null-terminated C-style strings can be easily converted to a +Slice: + +```c++ +leveldb::Slice s1 = "hello"; + +std::string str("world"); +leveldb::Slice s2 = str; +``` + +A Slice can be easily converted back to a C++ string: + +```c++ +std::string str = s1.ToString(); +assert(str == std::string("hello")); +``` + +Be careful when using Slices since it is up to the caller to ensure that the +external byte array into which the Slice points remains live while the Slice is +in use. For example, the following is buggy: + +```c++ +leveldb::Slice slice; +if (...) { + std::string str = ...; + slice = str; +} +Use(slice); +``` + +When the if statement goes out of scope, str will be destroyed and the backing +storage for slice will disappear. + +## Comparators + +The preceding examples used the default ordering function for key, which orders +bytes lexicographically. You can however supply a custom comparator when opening +a database. For example, suppose each database key consists of two numbers and +we should sort by the first number, breaking ties by the second number. First, +define a proper subclass of `leveldb::Comparator` that expresses these rules: + +```c++ +class TwoPartComparator : public leveldb::Comparator { + public: + // Three-way comparison function: + // if a < b: negative result + // if a > b: positive result + // else: zero result + int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const { + int a1, a2, b1, b2; + ParseKey(a, &a1, &a2); + ParseKey(b, &b1, &b2); + if (a1 < b1) return -1; + if (a1 > b1) return +1; + if (a2 < b2) return -1; + if (a2 > b2) return +1; + return 0; + } + + // Ignore the following methods for now: + const char* Name() const { return "TwoPartComparator"; } + void FindShortestSeparator(std::string*, const leveldb::Slice&) const {} + void FindShortSuccessor(std::string*) const {} +}; +``` + +Now create a database using this custom comparator: + +```c++ +TwoPartComparator cmp; +leveldb::DB* db; +leveldb::Options options; +options.create_if_missing = true; +options.comparator = &cmp; +leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db); +... +``` + +### Backwards compatibility + +The result of the comparator's Name method is attached to the database when it +is created, and is checked on every subsequent database open. If the name +changes, the `leveldb::DB::Open` call will fail. Therefore, change the name if +and only if the new key format and comparison function are incompatible with +existing databases, and it is ok to discard the contents of all existing +databases. + +You can however still gradually evolve your key format over time with a little +bit of pre-planning. For example, you could store a version number at the end of +each key (one byte should suffice for most uses). When you wish to switch to a +new key format (e.g., adding an optional third part to the keys processed by +`TwoPartComparator`), (a) keep the same comparator name (b) increment the +version number for new keys (c) change the comparator function so it uses the +version numbers found in the keys to decide how to interpret them. + +## Performance + +Performance can be tuned by changing the default values of the types defined in +`include/leveldb/options.h`. + +### Block size + +leveldb groups adjacent keys together into the same block and such a block is +the unit of transfer to and from persistent storage. The default block size is +approximately 4096 uncompressed bytes. Applications that mostly do bulk scans +over the contents of the database may wish to increase this size. Applications +that do a lot of point reads of small values may wish to switch to a smaller +block size if performance measurements indicate an improvement. There isn't much +benefit in using blocks smaller than one kilobyte, or larger than a few +megabytes. Also note that compression will be more effective with larger block +sizes. + +### Compression + +Each block is individually compressed before being written to persistent +storage. Compression is on by default since the default compression method is +very fast, and is automatically disabled for uncompressible data. In rare cases, +applications may want to disable compression entirely, but should only do so if +benchmarks show a performance improvement: + +```c++ +leveldb::Options options; +options.compression = leveldb::kNoCompression; +... leveldb::DB::Open(options, name, ...) .... +``` + +### Cache + +The contents of the database are stored in a set of files in the filesystem and +each file stores a sequence of compressed blocks. If options.cache is non-NULL, +it is used to cache frequently used uncompressed block contents. + +```c++ +#include "leveldb/cache.h" + +leveldb::Options options; +options.cache = leveldb::NewLRUCache(100 * 1048576); // 100MB cache +leveldb::DB* db; +leveldb::DB::Open(options, name, &db); +... use the db ... +delete db +delete options.cache; +``` + +Note that the cache holds uncompressed data, and therefore it should be sized +according to application level data sizes, without any reduction from +compression. (Caching of compressed blocks is left to the operating system +buffer cache, or any custom Env implementation provided by the client.) + +When performing a bulk read, the application may wish to disable caching so that +the data processed by the bulk read does not end up displacing most of the +cached contents. A per-iterator option can be used to achieve this: + +```c++ +leveldb::ReadOptions options; +options.fill_cache = false; +leveldb::Iterator* it = db->NewIterator(options); +for (it->SeekToFirst(); it->Valid(); it->Next()) { + ... +} +``` + +### Key Layout + +Note that the unit of disk transfer and caching is a block. Adjacent keys +(according to the database sort order) will usually be placed in the same block. +Therefore the application can improve its performance by placing keys that are +accessed together near each other and placing infrequently used keys in a +separate region of the key space. + +For example, suppose we are implementing a simple file system on top of leveldb. +The types of entries we might wish to store are: + + filename -> permission-bits, length, list of file_block_ids + file_block_id -> data + +We might want to prefix filename keys with one letter (say '/') and the +`file_block_id` keys with a different letter (say '0') so that scans over just +the metadata do not force us to fetch and cache bulky file contents. + +### Filters + +Because of the way leveldb data is organized on disk, a single `Get()` call may +involve multiple reads from disk. The optional FilterPolicy mechanism can be +used to reduce the number of disk reads substantially. + +```c++ +leveldb::Options options; +options.filter_policy = NewBloomFilterPolicy(10); +leveldb::DB* db; +leveldb::DB::Open(options, "/tmp/testdb", &db); +... use the database ... +delete db; +delete options.filter_policy; +``` + +The preceding code associates a Bloom filter based filtering policy with the +database. Bloom filter based filtering relies on keeping some number of bits of +data in memory per key (in this case 10 bits per key since that is the argument +we passed to `NewBloomFilterPolicy`). This filter will reduce the number of +unnecessary disk reads needed for Get() calls by a factor of approximately +a 100. Increasing the bits per key will lead to a larger reduction at the cost +of more memory usage. We recommend that applications whose working set does not +fit in memory and that do a lot of random reads set a filter policy. + +If you are using a custom comparator, you should ensure that the filter policy +you are using is compatible with your comparator. For example, consider a +comparator that ignores trailing spaces when comparing keys. +`NewBloomFilterPolicy` must not be used with such a comparator. Instead, the +application should provide a custom filter policy that also ignores trailing +spaces. For example: + +```c++ +class CustomFilterPolicy : public leveldb::FilterPolicy { + private: + FilterPolicy* builtin_policy_; + + public: + CustomFilterPolicy() : builtin_policy_(NewBloomFilterPolicy(10)) {} + ~CustomFilterPolicy() { delete builtin_policy_; } + + const char* Name() const { return "IgnoreTrailingSpacesFilter"; } + + void CreateFilter(const Slice* keys, int n, std::string* dst) const { + // Use builtin bloom filter code after removing trailing spaces + std::vector trimmed(n); + for (int i = 0; i < n; i++) { + trimmed[i] = RemoveTrailingSpaces(keys[i]); + } + return builtin_policy_->CreateFilter(&trimmed[i], n, dst); + } +}; +``` + +Advanced applications may provide a filter policy that does not use a bloom +filter but uses some other mechanism for summarizing a set of keys. See +`leveldb/filter_policy.h` for detail. + +## Checksums + +leveldb associates checksums with all data it stores in the file system. There +are two separate controls provided over how aggressively these checksums are +verified: + +`ReadOptions::verify_checksums` may be set to true to force checksum +verification of all data that is read from the file system on behalf of a +particular read. By default, no such verification is done. + +`Options::paranoid_checks` may be set to true before opening a database to make +the database implementation raise an error as soon as it detects an internal +corruption. Depending on which portion of the database has been corrupted, the +error may be raised when the database is opened, or later by another database +operation. By default, paranoid checking is off so that the database can be used +even if parts of its persistent storage have been corrupted. + +If a database is corrupted (perhaps it cannot be opened when paranoid checking +is turned on), the `leveldb::RepairDB` function may be used to recover as much +of the data as possible + +## Approximate Sizes + +The `GetApproximateSizes` method can used to get the approximate number of bytes +of file system space used by one or more key ranges. + +```c++ +leveldb::Range ranges[2]; +ranges[0] = leveldb::Range("a", "c"); +ranges[1] = leveldb::Range("x", "z"); +uint64_t sizes[2]; +leveldb::Status s = db->GetApproximateSizes(ranges, 2, sizes); +``` + +The preceding call will set `sizes[0]` to the approximate number of bytes of +file system space used by the key range `[a..c)` and `sizes[1]` to the +approximate number of bytes used by the key range `[x..z)`. + +## Environment + +All file operations (and other operating system calls) issued by the leveldb +implementation are routed through a `leveldb::Env` object. Sophisticated clients +may wish to provide their own Env implementation to get better control. +For example, an application may introduce artificial delays in the file IO +paths to limit the impact of leveldb on other activities in the system. + +```c++ +class SlowEnv : public leveldb::Env { + ... implementation of the Env interface ... +}; + +SlowEnv env; +leveldb::Options options; +options.env = &env; +Status s = leveldb::DB::Open(options, ...); +``` + +## Porting + +leveldb may be ported to a new platform by providing platform specific +implementations of the types/methods/functions exported by +`leveldb/port/port.h`. See `leveldb/port/port_example.h` for more details. + +In addition, the new platform may need a new default `leveldb::Env` +implementation. See `leveldb/util/env_posix.h` for an example. + +## Other Information + +Details about the leveldb implementation may be found in the following +documents: + +1. [Implementation notes](impl.md) +2. [Format of an immutable Table file](table_format.md) +3. [Format of a log file](log_format.md) diff --git a/src/leveldb/doc/log_format.md b/src/leveldb/doc/log_format.md new file mode 100644 index 000000000000..f32cb5d7dac4 --- /dev/null +++ b/src/leveldb/doc/log_format.md @@ -0,0 +1,75 @@ +leveldb Log format +================== +The log file contents are a sequence of 32KB blocks. The only exception is that +the tail of the file may contain a partial block. + +Each block consists of a sequence of records: + + block := record* trailer? + record := + checksum: uint32 // crc32c of type and data[] ; little-endian + length: uint16 // little-endian + type: uint8 // One of FULL, FIRST, MIDDLE, LAST + data: uint8[length] + +A record never starts within the last six bytes of a block (since it won't fit). +Any leftover bytes here form the trailer, which must consist entirely of zero +bytes and must be skipped by readers. + +Aside: if exactly seven bytes are left in the current block, and a new non-zero +length record is added, the writer must emit a FIRST record (which contains zero +bytes of user data) to fill up the trailing seven bytes of the block and then +emit all of the user data in subsequent blocks. + +More types may be added in the future. Some Readers may skip record types they +do not understand, others may report that some data was skipped. + + FULL == 1 + FIRST == 2 + MIDDLE == 3 + LAST == 4 + +The FULL record contains the contents of an entire user record. + +FIRST, MIDDLE, LAST are types used for user records that have been split into +multiple fragments (typically because of block boundaries). FIRST is the type +of the first fragment of a user record, LAST is the type of the last fragment of +a user record, and MIDDLE is the type of all interior fragments of a user +record. + +Example: consider a sequence of user records: + + A: length 1000 + B: length 97270 + C: length 8000 + +**A** will be stored as a FULL record in the first block. + +**B** will be split into three fragments: first fragment occupies the rest of +the first block, second fragment occupies the entirety of the second block, and +the third fragment occupies a prefix of the third block. This will leave six +bytes free in the third block, which will be left empty as the trailer. + +**C** will be stored as a FULL record in the fourth block. + +---- + +## Some benefits over the recordio format: + +1. We do not need any heuristics for resyncing - just go to next block boundary + and scan. If there is a corruption, skip to the next block. As a + side-benefit, we do not get confused when part of the contents of one log + file are embedded as a record inside another log file. + +2. Splitting at approximate boundaries (e.g., for mapreduce) is simple: find the + next block boundary and skip records until we hit a FULL or FIRST record. + +3. We do not need extra buffering for large records. + +## Some downsides compared to recordio format: + +1. No packing of tiny records. This could be fixed by adding a new record type, + so it is a shortcoming of the current implementation, not necessarily the + format. + +2. No compression. Again, this could be fixed by adding new record types. diff --git a/src/leveldb/doc/log_format.txt b/src/leveldb/doc/log_format.txt deleted file mode 100644 index 4cca5ef6ead3..000000000000 --- a/src/leveldb/doc/log_format.txt +++ /dev/null @@ -1,75 +0,0 @@ -The log file contents are a sequence of 32KB blocks. The only -exception is that the tail of the file may contain a partial block. - -Each block consists of a sequence of records: - block := record* trailer? - record := - checksum: uint32 // crc32c of type and data[] ; little-endian - length: uint16 // little-endian - type: uint8 // One of FULL, FIRST, MIDDLE, LAST - data: uint8[length] - -A record never starts within the last six bytes of a block (since it -won't fit). Any leftover bytes here form the trailer, which must -consist entirely of zero bytes and must be skipped by readers. - -Aside: if exactly seven bytes are left in the current block, and a new -non-zero length record is added, the writer must emit a FIRST record -(which contains zero bytes of user data) to fill up the trailing seven -bytes of the block and then emit all of the user data in subsequent -blocks. - -More types may be added in the future. Some Readers may skip record -types they do not understand, others may report that some data was -skipped. - -FULL == 1 -FIRST == 2 -MIDDLE == 3 -LAST == 4 - -The FULL record contains the contents of an entire user record. - -FIRST, MIDDLE, LAST are types used for user records that have been -split into multiple fragments (typically because of block boundaries). -FIRST is the type of the first fragment of a user record, LAST is the -type of the last fragment of a user record, and MIDDLE is the type of -all interior fragments of a user record. - -Example: consider a sequence of user records: - A: length 1000 - B: length 97270 - C: length 8000 -A will be stored as a FULL record in the first block. - -B will be split into three fragments: first fragment occupies the rest -of the first block, second fragment occupies the entirety of the -second block, and the third fragment occupies a prefix of the third -block. This will leave six bytes free in the third block, which will -be left empty as the trailer. - -C will be stored as a FULL record in the fourth block. - -=================== - -Some benefits over the recordio format: - -(1) We do not need any heuristics for resyncing - just go to next -block boundary and scan. If there is a corruption, skip to the next -block. As a side-benefit, we do not get confused when part of the -contents of one log file are embedded as a record inside another log -file. - -(2) Splitting at approximate boundaries (e.g., for mapreduce) is -simple: find the next block boundary and skip records until we -hit a FULL or FIRST record. - -(3) We do not need extra buffering for large records. - -Some downsides compared to recordio format: - -(1) No packing of tiny records. This could be fixed by adding a new -record type, so it is a shortcoming of the current implementation, -not necessarily the format. - -(2) No compression. Again, this could be fixed by adding new record types. diff --git a/src/leveldb/doc/table_format.md b/src/leveldb/doc/table_format.md new file mode 100644 index 000000000000..5fe7e72411b8 --- /dev/null +++ b/src/leveldb/doc/table_format.md @@ -0,0 +1,107 @@ +leveldb File format +=================== + + + [data block 1] + [data block 2] + ... + [data block N] + [meta block 1] + ... + [meta block K] + [metaindex block] + [index block] + [Footer] (fixed size; starts at file_size - sizeof(Footer)) + + +The file contains internal pointers. Each such pointer is called +a BlockHandle and contains the following information: + + offset: varint64 + size: varint64 + +See [varints](https://developers.google.com/protocol-buffers/docs/encoding#varints) +for an explanation of varint64 format. + +1. The sequence of key/value pairs in the file are stored in sorted +order and partitioned into a sequence of data blocks. These blocks +come one after another at the beginning of the file. Each data block +is formatted according to the code in `block_builder.cc`, and then +optionally compressed. + +2. After the data blocks we store a bunch of meta blocks. The +supported meta block types are described below. More meta block types +may be added in the future. Each meta block is again formatted using +`block_builder.cc` and then optionally compressed. + +3. A "metaindex" block. It contains one entry for every other meta +block where the key is the name of the meta block and the value is a +BlockHandle pointing to that meta block. + +4. An "index" block. This block contains one entry per data block, +where the key is a string >= last key in that data block and before +the first key in the successive data block. The value is the +BlockHandle for the data block. + +5. At the very end of the file is a fixed length footer that contains +the BlockHandle of the metaindex and index blocks as well as a magic number. + + metaindex_handle: char[p]; // Block handle for metaindex + index_handle: char[q]; // Block handle for index + padding: char[40-p-q];// zeroed bytes to make fixed length + // (40==2*BlockHandle::kMaxEncodedLength) + magic: fixed64; // == 0xdb4775248b80fb57 (little-endian) + +## "filter" Meta Block + +If a `FilterPolicy` was specified when the database was opened, a +filter block is stored in each table. The "metaindex" block contains +an entry that maps from `filter.` to the BlockHandle for the filter +block where `` is the string returned by the filter policy's +`Name()` method. + +The filter block stores a sequence of filters, where filter i contains +the output of `FilterPolicy::CreateFilter()` on all keys that are stored +in a block whose file offset falls within the range + + [ i*base ... (i+1)*base-1 ] + +Currently, "base" is 2KB. So for example, if blocks X and Y start in +the range `[ 0KB .. 2KB-1 ]`, all of the keys in X and Y will be +converted to a filter by calling `FilterPolicy::CreateFilter()`, and the +resulting filter will be stored as the first filter in the filter +block. + +The filter block is formatted as follows: + + [filter 0] + [filter 1] + [filter 2] + ... + [filter N-1] + + [offset of filter 0] : 4 bytes + [offset of filter 1] : 4 bytes + [offset of filter 2] : 4 bytes + ... + [offset of filter N-1] : 4 bytes + + [offset of beginning of offset array] : 4 bytes + lg(base) : 1 byte + +The offset array at the end of the filter block allows efficient +mapping from a data block offset to the corresponding filter. + +## "stats" Meta Block + +This meta block contains a bunch of stats. The key is the name +of the statistic. The value contains the statistic. + +TODO(postrelease): record following stats. + + data size + index size + key size (uncompressed) + value size (uncompressed) + number of entries + number of data blocks diff --git a/src/leveldb/doc/table_format.txt b/src/leveldb/doc/table_format.txt deleted file mode 100644 index ca8f9b4460ad..000000000000 --- a/src/leveldb/doc/table_format.txt +++ /dev/null @@ -1,104 +0,0 @@ -File format -=========== - - - [data block 1] - [data block 2] - ... - [data block N] - [meta block 1] - ... - [meta block K] - [metaindex block] - [index block] - [Footer] (fixed size; starts at file_size - sizeof(Footer)) - - -The file contains internal pointers. Each such pointer is called -a BlockHandle and contains the following information: - offset: varint64 - size: varint64 -See https://developers.google.com/protocol-buffers/docs/encoding#varints -for an explanation of varint64 format. - -(1) The sequence of key/value pairs in the file are stored in sorted -order and partitioned into a sequence of data blocks. These blocks -come one after another at the beginning of the file. Each data block -is formatted according to the code in block_builder.cc, and then -optionally compressed. - -(2) After the data blocks we store a bunch of meta blocks. The -supported meta block types are described below. More meta block types -may be added in the future. Each meta block is again formatted using -block_builder.cc and then optionally compressed. - -(3) A "metaindex" block. It contains one entry for every other meta -block where the key is the name of the meta block and the value is a -BlockHandle pointing to that meta block. - -(4) An "index" block. This block contains one entry per data block, -where the key is a string >= last key in that data block and before -the first key in the successive data block. The value is the -BlockHandle for the data block. - -(6) At the very end of the file is a fixed length footer that contains -the BlockHandle of the metaindex and index blocks as well as a magic number. - metaindex_handle: char[p]; // Block handle for metaindex - index_handle: char[q]; // Block handle for index - padding: char[40-p-q]; // zeroed bytes to make fixed length - // (40==2*BlockHandle::kMaxEncodedLength) - magic: fixed64; // == 0xdb4775248b80fb57 (little-endian) - -"filter" Meta Block -------------------- - -If a "FilterPolicy" was specified when the database was opened, a -filter block is stored in each table. The "metaindex" block contains -an entry that maps from "filter." to the BlockHandle for the filter -block where "" is the string returned by the filter policy's -"Name()" method. - -The filter block stores a sequence of filters, where filter i contains -the output of FilterPolicy::CreateFilter() on all keys that are stored -in a block whose file offset falls within the range - - [ i*base ... (i+1)*base-1 ] - -Currently, "base" is 2KB. So for example, if blocks X and Y start in -the range [ 0KB .. 2KB-1 ], all of the keys in X and Y will be -converted to a filter by calling FilterPolicy::CreateFilter(), and the -resulting filter will be stored as the first filter in the filter -block. - -The filter block is formatted as follows: - - [filter 0] - [filter 1] - [filter 2] - ... - [filter N-1] - - [offset of filter 0] : 4 bytes - [offset of filter 1] : 4 bytes - [offset of filter 2] : 4 bytes - ... - [offset of filter N-1] : 4 bytes - - [offset of beginning of offset array] : 4 bytes - lg(base) : 1 byte - -The offset array at the end of the filter block allows efficient -mapping from a data block offset to the corresponding filter. - -"stats" Meta Block ------------------- - -This meta block contains a bunch of stats. The key is the name -of the statistic. The value contains the statistic. -TODO(postrelease): record following stats. - data size - index size - key size (uncompressed) - value size (uncompressed) - number of entries - number of data blocks diff --git a/src/leveldb/include/leveldb/db.h b/src/leveldb/include/leveldb/db.h index 9752cbad512d..bfab10a0b725 100644 --- a/src/leveldb/include/leveldb/db.h +++ b/src/leveldb/include/leveldb/db.h @@ -14,7 +14,7 @@ namespace leveldb { // Update Makefile if you change these static const int kMajorVersion = 1; -static const int kMinorVersion = 19; +static const int kMinorVersion = 20; struct Options; struct ReadOptions; diff --git a/src/leveldb/include/leveldb/options.h b/src/leveldb/include/leveldb/options.h index 83a1ef39a481..976e38122aaf 100644 --- a/src/leveldb/include/leveldb/options.h +++ b/src/leveldb/include/leveldb/options.h @@ -112,6 +112,18 @@ struct Options { // Default: 16 int block_restart_interval; + // Leveldb will write up to this amount of bytes to a file before + // switching to a new one. + // Most clients should leave this parameter alone. However if your + // filesystem is more efficient with larger files, you could + // consider increasing the value. The downside will be longer + // compactions and hence longer latency/performance hiccups. + // Another reason to increase this parameter might be when you are + // initially populating a large database. + // + // Default: 2MB + size_t max_file_size; + // Compress blocks using the specified compression algorithm. This // parameter can be changed dynamically. // diff --git a/src/leveldb/port/port_example.h b/src/leveldb/port/port_example.h index ab9e489b32d8..97bd669a5ed6 100644 --- a/src/leveldb/port/port_example.h +++ b/src/leveldb/port/port_example.h @@ -129,6 +129,12 @@ extern bool Snappy_Uncompress(const char* input_data, size_t input_length, // The concatenation of all "data[0,n-1]" fragments is the heap profile. extern bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg); +// Extend the CRC to include the first n bytes of buf. +// +// Returns zero if the CRC cannot be extended using acceleration, else returns +// the newly extended CRC value (which may also be zero). +uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size); + } // namespace port } // namespace leveldb diff --git a/src/leveldb/port/port_posix.h b/src/leveldb/port/port_posix.h index ccca9939d3dc..7e8213b22eca 100644 --- a/src/leveldb/port/port_posix.h +++ b/src/leveldb/port/port_posix.h @@ -152,6 +152,8 @@ inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { return false; } +uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size); + } // namespace port } // namespace leveldb diff --git a/src/leveldb/port/port_posix_sse.cc b/src/leveldb/port/port_posix_sse.cc new file mode 100644 index 000000000000..1e519ba0b64b --- /dev/null +++ b/src/leveldb/port/port_posix_sse.cc @@ -0,0 +1,129 @@ +// Copyright 2016 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A portable implementation of crc32c, optimized to handle +// four bytes at a time. +// +// In a separate source file to allow this accelerated CRC32C function to be +// compiled with the appropriate compiler flags to enable x86 SSE 4.2 +// instructions. + +#include +#include +#include "port/port.h" + +#if defined(LEVELDB_PLATFORM_POSIX_SSE) + +#if defined(_MSC_VER) +#include +#elif defined(__GNUC__) && defined(__SSE4_2__) +#include +#include +#endif + +#endif // defined(LEVELDB_PLATFORM_POSIX_SSE) + +namespace leveldb { +namespace port { + +#if defined(LEVELDB_PLATFORM_POSIX_SSE) + +// Used to fetch a naturally-aligned 32-bit word in little endian byte-order +static inline uint32_t LE_LOAD32(const uint8_t *p) { + // SSE is x86 only, so ensured that |p| is always little-endian. + uint32_t word; + memcpy(&word, p, sizeof(word)); + return word; +} + +#if defined(_M_X64) || defined(__x86_64__) // LE_LOAD64 is only used on x64. + +// Used to fetch a naturally-aligned 64-bit word in little endian byte-order +static inline uint64_t LE_LOAD64(const uint8_t *p) { + uint64_t dword; + memcpy(&dword, p, sizeof(dword)); + return dword; +} + +#endif // defined(_M_X64) || defined(__x86_64__) + +static inline bool HaveSSE42() { +#if defined(_MSC_VER) + int cpu_info[4]; + __cpuid(cpu_info, 1); + return (cpu_info[2] & (1 << 20)) != 0; +#elif defined(__GNUC__) + unsigned int eax, ebx, ecx, edx; + __get_cpuid(1, &eax, &ebx, &ecx, &edx); + return (ecx & (1 << 20)) != 0; +#else + return false; +#endif +} + +#endif // defined(LEVELDB_PLATFORM_POSIX_SSE) + +// For further improvements see Intel publication at: +// http://download.intel.com/design/intarch/papers/323405.pdf +uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) { +#if !defined(LEVELDB_PLATFORM_POSIX_SSE) + return 0; +#else + static bool have = HaveSSE42(); + if (!have) { + return 0; + } + + const uint8_t *p = reinterpret_cast(buf); + const uint8_t *e = p + size; + uint32_t l = crc ^ 0xffffffffu; + +#define STEP1 do { \ + l = _mm_crc32_u8(l, *p++); \ +} while (0) +#define STEP4 do { \ + l = _mm_crc32_u32(l, LE_LOAD32(p)); \ + p += 4; \ +} while (0) +#define STEP8 do { \ + l = _mm_crc32_u64(l, LE_LOAD64(p)); \ + p += 8; \ +} while (0) + + if (size > 16) { + // Process unaligned bytes + for (unsigned int i = reinterpret_cast(p) % 8; i; --i) { + STEP1; + } + + // _mm_crc32_u64 is only available on x64. +#if defined(_M_X64) || defined(__x86_64__) + // Process 8 bytes at a time + while ((e-p) >= 8) { + STEP8; + } + // Process 4 bytes at a time + if ((e-p) >= 4) { + STEP4; + } +#else // !(defined(_M_X64) || defined(__x86_64__)) + // Process 4 bytes at a time + while ((e-p) >= 4) { + STEP4; + } +#endif // defined(_M_X64) || defined(__x86_64__) + } + // Process the last few bytes + while (p != e) { + STEP1; + } +#undef STEP8 +#undef STEP4 +#undef STEP1 + return l ^ 0xffffffffu; +#endif // defined(LEVELDB_PLATFORM_POSIX_SSE) +} + +} // namespace port +} // namespace leveldb diff --git a/src/leveldb/port/port_win.h b/src/leveldb/port/port_win.h index 45bf2f0ea749..500900482283 100644 --- a/src/leveldb/port/port_win.h +++ b/src/leveldb/port/port_win.h @@ -168,6 +168,8 @@ inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { return false; } +uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size); + } } diff --git a/src/leveldb/table/filter_block.cc b/src/leveldb/table/filter_block.cc index 4e78b954f8d9..1ed5134170e5 100644 --- a/src/leveldb/table/filter_block.cc +++ b/src/leveldb/table/filter_block.cc @@ -9,7 +9,7 @@ namespace leveldb { -// See doc/table_format.txt for an explanation of the filter block format. +// See doc/table_format.md for an explanation of the filter block format. // Generate new filter every 2KB of data static const size_t kFilterBaseLg = 11; diff --git a/src/leveldb/util/crc32c.cc b/src/leveldb/util/crc32c.cc index 6db9e770774d..edd61cfd6fca 100644 --- a/src/leveldb/util/crc32c.cc +++ b/src/leveldb/util/crc32c.cc @@ -8,6 +8,8 @@ #include "util/crc32c.h" #include + +#include "port/port.h" #include "util/coding.h" namespace leveldb { @@ -283,7 +285,23 @@ static inline uint32_t LE_LOAD32(const uint8_t *p) { return DecodeFixed32(reinterpret_cast(p)); } +// Determine if the CPU running this program can accelerate the CRC32C +// calculation. +static bool CanAccelerateCRC32C() { + // port::AcceleretedCRC32C returns zero when unable to accelerate. + static const char kTestCRCBuffer[] = "TestCRCBuffer"; + static const char kBufSize = sizeof(kTestCRCBuffer) - 1; + static const uint32_t kTestCRCValue = 0xdcbc59fa; + + return port::AcceleratedCRC32C(0, kTestCRCBuffer, kBufSize) == kTestCRCValue; +} + uint32_t Extend(uint32_t crc, const char* buf, size_t size) { + static bool accelerate = CanAccelerateCRC32C(); + if (accelerate) { + return port::AcceleratedCRC32C(crc, buf, size); + } + const uint8_t *p = reinterpret_cast(buf); const uint8_t *e = p + size; uint32_t l = crc ^ 0xffffffffu; diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc index e0fca52f4632..dd852af354c8 100644 --- a/src/leveldb/util/env_posix.cc +++ b/src/leveldb/util/env_posix.cc @@ -11,12 +11,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include "leveldb/env.h" #include "leveldb/slice.h" @@ -24,15 +26,70 @@ #include "util/logging.h" #include "util/mutexlock.h" #include "util/posix_logger.h" +#include "util/env_posix_test_helper.h" namespace leveldb { namespace { +static int open_read_only_file_limit = -1; +static int mmap_limit = -1; + static Status IOError(const std::string& context, int err_number) { return Status::IOError(context, strerror(err_number)); } +// Helper class to limit resource usage to avoid exhaustion. +// Currently used to limit read-only file descriptors and mmap file usage +// so that we do not end up running out of file descriptors, virtual memory, +// or running into kernel performance problems for very large databases. +class Limiter { + public: + // Limit maximum number of resources to |n|. + Limiter(intptr_t n) { + SetAllowed(n); + } + + // If another resource is available, acquire it and return true. + // Else return false. + bool Acquire() { + if (GetAllowed() <= 0) { + return false; + } + MutexLock l(&mu_); + intptr_t x = GetAllowed(); + if (x <= 0) { + return false; + } else { + SetAllowed(x - 1); + return true; + } + } + + // Release a resource acquired by a previous call to Acquire() that returned + // true. + void Release() { + MutexLock l(&mu_); + SetAllowed(GetAllowed() + 1); + } + + private: + port::Mutex mu_; + port::AtomicPointer allowed_; + + intptr_t GetAllowed() const { + return reinterpret_cast(allowed_.Acquire_Load()); + } + + // REQUIRES: mu_ must be held + void SetAllowed(intptr_t v) { + allowed_.Release_Store(reinterpret_cast(v)); + } + + Limiter(const Limiter&); + void operator=(const Limiter&); +}; + class PosixSequentialFile: public SequentialFile { private: std::string filename_; @@ -70,73 +127,51 @@ class PosixSequentialFile: public SequentialFile { class PosixRandomAccessFile: public RandomAccessFile { private: std::string filename_; + bool temporary_fd_; // If true, fd_ is -1 and we open on every read. int fd_; + Limiter* limiter_; public: - PosixRandomAccessFile(const std::string& fname, int fd) - : filename_(fname), fd_(fd) { } - virtual ~PosixRandomAccessFile() { close(fd_); } + PosixRandomAccessFile(const std::string& fname, int fd, Limiter* limiter) + : filename_(fname), fd_(fd), limiter_(limiter) { + temporary_fd_ = !limiter->Acquire(); + if (temporary_fd_) { + // Open file on every access. + close(fd_); + fd_ = -1; + } + } + + virtual ~PosixRandomAccessFile() { + if (!temporary_fd_) { + close(fd_); + limiter_->Release(); + } + } virtual Status Read(uint64_t offset, size_t n, Slice* result, char* scratch) const { + int fd = fd_; + if (temporary_fd_) { + fd = open(filename_.c_str(), O_RDONLY); + if (fd < 0) { + return IOError(filename_, errno); + } + } + Status s; - ssize_t r = pread(fd_, scratch, n, static_cast(offset)); + ssize_t r = pread(fd, scratch, n, static_cast(offset)); *result = Slice(scratch, (r < 0) ? 0 : r); if (r < 0) { // An error: return a non-ok status s = IOError(filename_, errno); } - return s; - } -}; - -// Helper class to limit mmap file usage so that we do not end up -// running out virtual memory or running into kernel performance -// problems for very large databases. -class MmapLimiter { - public: - // Up to 1000 mmaps for 64-bit binaries; none for smaller pointer sizes. - MmapLimiter() { - SetAllowed(sizeof(void*) >= 8 ? 1000 : 0); - } - - // If another mmap slot is available, acquire it and return true. - // Else return false. - bool Acquire() { - if (GetAllowed() <= 0) { - return false; - } - MutexLock l(&mu_); - intptr_t x = GetAllowed(); - if (x <= 0) { - return false; - } else { - SetAllowed(x - 1); - return true; + if (temporary_fd_) { + // Close the temporary file descriptor opened earlier. + close(fd); } + return s; } - - // Release a slot acquired by a previous call to Acquire() that returned true. - void Release() { - MutexLock l(&mu_); - SetAllowed(GetAllowed() + 1); - } - - private: - port::Mutex mu_; - port::AtomicPointer allowed_; - - intptr_t GetAllowed() const { - return reinterpret_cast(allowed_.Acquire_Load()); - } - - // REQUIRES: mu_ must be held - void SetAllowed(intptr_t v) { - allowed_.Release_Store(reinterpret_cast(v)); - } - - MmapLimiter(const MmapLimiter&); - void operator=(const MmapLimiter&); }; // mmap() based random-access @@ -145,12 +180,12 @@ class PosixMmapReadableFile: public RandomAccessFile { std::string filename_; void* mmapped_region_; size_t length_; - MmapLimiter* limiter_; + Limiter* limiter_; public: // base[0,length-1] contains the mmapped contents of the file. PosixMmapReadableFile(const std::string& fname, void* base, size_t length, - MmapLimiter* limiter) + Limiter* limiter) : filename_(fname), mmapped_region_(base), length_(length), limiter_(limiter) { } @@ -231,7 +266,7 @@ class PosixWritableFile : public WritableFile { if (fd < 0) { s = IOError(dir, errno); } else { - if (fsync(fd) < 0) { + if (fsync(fd) < 0 && errno != EINVAL) { s = IOError(dir, errno); } close(fd); @@ -333,7 +368,7 @@ class PosixEnv : public Env { mmap_limit_.Release(); } } else { - *result = new PosixRandomAccessFile(fname, fd); + *result = new PosixRandomAccessFile(fname, fd, &fd_limit_); } return s; } @@ -533,10 +568,42 @@ class PosixEnv : public Env { BGQueue queue_; PosixLockTable locks_; - MmapLimiter mmap_limit_; + Limiter mmap_limit_; + Limiter fd_limit_; }; -PosixEnv::PosixEnv() : started_bgthread_(false) { +// Return the maximum number of concurrent mmaps. +static int MaxMmaps() { + if (mmap_limit >= 0) { + return mmap_limit; + } + // Up to 1000 mmaps for 64-bit binaries; none for smaller pointer sizes. + mmap_limit = sizeof(void*) >= 8 ? 1000 : 0; + return mmap_limit; +} + +// Return the maximum number of read-only files to keep open. +static intptr_t MaxOpenFiles() { + if (open_read_only_file_limit >= 0) { + return open_read_only_file_limit; + } + struct rlimit rlim; + if (getrlimit(RLIMIT_NOFILE, &rlim)) { + // getrlimit failed, fallback to hard-coded default. + open_read_only_file_limit = 50; + } else if (rlim.rlim_cur == RLIM_INFINITY) { + open_read_only_file_limit = std::numeric_limits::max(); + } else { + // Allow use of 20% of available file descriptors for read-only files. + open_read_only_file_limit = rlim.rlim_cur / 5; + } + return open_read_only_file_limit; +} + +PosixEnv::PosixEnv() + : started_bgthread_(false), + mmap_limit_(MaxMmaps()), + fd_limit_(MaxOpenFiles()) { PthreadCall("mutex_init", pthread_mutex_init(&mu_, NULL)); PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, NULL)); } @@ -611,6 +678,16 @@ static pthread_once_t once = PTHREAD_ONCE_INIT; static Env* default_env; static void InitDefaultEnv() { default_env = new PosixEnv; } +void EnvPosixTestHelper::SetReadOnlyFDLimit(int limit) { + assert(default_env == NULL); + open_read_only_file_limit = limit; +} + +void EnvPosixTestHelper::SetReadOnlyMMapLimit(int limit) { + assert(default_env == NULL); + mmap_limit = limit; +} + Env* Env::Default() { pthread_once(&once, InitDefaultEnv); return default_env; diff --git a/src/leveldb/util/env_posix_test.cc b/src/leveldb/util/env_posix_test.cc new file mode 100644 index 000000000000..295f8ae4409f --- /dev/null +++ b/src/leveldb/util/env_posix_test.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/env.h" + +#include "port/port.h" +#include "util/testharness.h" +#include "util/env_posix_test_helper.h" + +namespace leveldb { + +static const int kDelayMicros = 100000; +static const int kReadOnlyFileLimit = 4; +static const int kMMapLimit = 4; + +class EnvPosixTest { + public: + Env* env_; + EnvPosixTest() : env_(Env::Default()) { } + + static void SetFileLimits(int read_only_file_limit, int mmap_limit) { + EnvPosixTestHelper::SetReadOnlyFDLimit(read_only_file_limit); + EnvPosixTestHelper::SetReadOnlyMMapLimit(mmap_limit); + } +}; + +TEST(EnvPosixTest, TestOpenOnRead) { + // Write some test data to a single file that will be opened |n| times. + std::string test_dir; + ASSERT_OK(env_->GetTestDirectory(&test_dir)); + std::string test_file = test_dir + "/open_on_read.txt"; + + FILE* f = fopen(test_file.c_str(), "w"); + ASSERT_TRUE(f != NULL); + const char kFileData[] = "abcdefghijklmnopqrstuvwxyz"; + fputs(kFileData, f); + fclose(f); + + // Open test file some number above the sum of the two limits to force + // open-on-read behavior of POSIX Env leveldb::RandomAccessFile. + const int kNumFiles = kReadOnlyFileLimit + kMMapLimit + 5; + leveldb::RandomAccessFile* files[kNumFiles] = {0}; + for (int i = 0; i < kNumFiles; i++) { + ASSERT_OK(env_->NewRandomAccessFile(test_file, &files[i])); + } + char scratch; + Slice read_result; + for (int i = 0; i < kNumFiles; i++) { + ASSERT_OK(files[i]->Read(i, 1, &read_result, &scratch)); + ASSERT_EQ(kFileData[i], read_result[0]); + } + for (int i = 0; i < kNumFiles; i++) { + delete files[i]; + } + ASSERT_OK(env_->DeleteFile(test_file)); +} + +} // namespace leveldb + +int main(int argc, char** argv) { + // All tests currently run with the same read-only file limits. + leveldb::EnvPosixTest::SetFileLimits(leveldb::kReadOnlyFileLimit, + leveldb::kMMapLimit); + return leveldb::test::RunAllTests(); +} diff --git a/src/leveldb/util/env_posix_test_helper.h b/src/leveldb/util/env_posix_test_helper.h new file mode 100644 index 000000000000..038696059826 --- /dev/null +++ b/src/leveldb/util/env_posix_test_helper.h @@ -0,0 +1,28 @@ +// Copyright 2017 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ +#define STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ + +namespace leveldb { + +class EnvPosixTest; + +// A helper for the POSIX Env to facilitate testing. +class EnvPosixTestHelper { + private: + friend class EnvPosixTest; + + // Set the maximum number of read-only files that will be opened. + // Must be called before creating an Env. + static void SetReadOnlyFDLimit(int limit); + + // Set the maximum number of read-only files that will be mapped via mmap. + // Must be called before creating an Env. + static void SetReadOnlyMMapLimit(int limit); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ diff --git a/src/leveldb/util/env_test.cc b/src/leveldb/util/env_test.cc index b72cb4438425..839ae56a1a49 100644 --- a/src/leveldb/util/env_test.cc +++ b/src/leveldb/util/env_test.cc @@ -10,29 +10,31 @@ namespace leveldb { static const int kDelayMicros = 100000; +static const int kReadOnlyFileLimit = 4; +static const int kMMapLimit = 4; -class EnvPosixTest { +class EnvTest { private: port::Mutex mu_; std::string events_; public: Env* env_; - EnvPosixTest() : env_(Env::Default()) { } + EnvTest() : env_(Env::Default()) { } }; static void SetBool(void* ptr) { reinterpret_cast(ptr)->NoBarrier_Store(ptr); } -TEST(EnvPosixTest, RunImmediately) { +TEST(EnvTest, RunImmediately) { port::AtomicPointer called (NULL); env_->Schedule(&SetBool, &called); - Env::Default()->SleepForMicroseconds(kDelayMicros); + env_->SleepForMicroseconds(kDelayMicros); ASSERT_TRUE(called.NoBarrier_Load() != NULL); } -TEST(EnvPosixTest, RunMany) { +TEST(EnvTest, RunMany) { port::AtomicPointer last_id (NULL); struct CB { @@ -59,7 +61,7 @@ TEST(EnvPosixTest, RunMany) { env_->Schedule(&CB::Run, &cb3); env_->Schedule(&CB::Run, &cb4); - Env::Default()->SleepForMicroseconds(kDelayMicros); + env_->SleepForMicroseconds(kDelayMicros); void* cur = last_id.Acquire_Load(); ASSERT_EQ(4, reinterpret_cast(cur)); } @@ -78,7 +80,7 @@ static void ThreadBody(void* arg) { s->mu.Unlock(); } -TEST(EnvPosixTest, StartThread) { +TEST(EnvTest, StartThread) { State state; state.val = 0; state.num_running = 3; @@ -92,7 +94,7 @@ TEST(EnvPosixTest, StartThread) { if (num == 0) { break; } - Env::Default()->SleepForMicroseconds(kDelayMicros); + env_->SleepForMicroseconds(kDelayMicros); } ASSERT_EQ(state.val, 3); } diff --git a/src/leveldb/util/env_win.cc b/src/leveldb/util/env_win.cc index b074b7579ec2..d32c4e676c3f 100644 --- a/src/leveldb/util/env_win.cc +++ b/src/leveldb/util/env_win.cc @@ -1,7 +1,7 @@ // This file contains source that originates from: // http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/env_win32.h // http://code.google.com/p/leveldbwin/source/browse/trunk/win32_impl_src/port_win32.cc -// Those files dont' have any explict license headers but the +// Those files don't have any explicit license headers but the // project (http://code.google.com/p/leveldbwin/) lists the 'New BSD License' // as the license. #if defined(LEVELDB_PLATFORM_WINDOWS) @@ -355,11 +355,13 @@ BOOL Win32SequentialFile::_Init() ToWidePath(_filename, path); _hFile = CreateFileW(path.c_str(), GENERIC_READ, - FILE_SHARE_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (_hFile == INVALID_HANDLE_VALUE) + _hFile = NULL; return _hFile ? TRUE : FALSE; } @@ -403,7 +405,7 @@ BOOL Win32RandomAccessFile::_Init( LPCWSTR path ) { BOOL bRet = FALSE; if(!_hFile) - _hFile = ::CreateFileW(path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, + _hFile = ::CreateFileW(path,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,NULL); if(!_hFile || _hFile == INVALID_HANDLE_VALUE ) _hFile = NULL; @@ -669,7 +671,7 @@ Status Win32Env::GetFileSize( const std::string& fname, uint64_t* file_size ) ToWidePath(ModifyPath(path), wpath); HANDLE file = ::CreateFileW(wpath.c_str(), - GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); LARGE_INTEGER li; if(::GetFileSizeEx(file,&li)){ *file_size = (uint64_t)li.QuadPart; diff --git a/src/leveldb/util/options.cc b/src/leveldb/util/options.cc index 8b618fb1ae85..b5e622761357 100644 --- a/src/leveldb/util/options.cc +++ b/src/leveldb/util/options.cc @@ -21,6 +21,7 @@ Options::Options() block_cache(NULL), block_size(4096), block_restart_interval(16), + max_file_size(2<<20), compression(kSnappyCompression), reuse_logs(false), filter_policy(NULL) { From a0bc91a5780bfa15970309de1161ea5c89342f27 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 13 Jun 2017 20:41:12 +0200 Subject: [PATCH 373/987] Merge #10480: Improve commit-check-script.sh 5432fc3 Fail on commit with VERIFY SCRIPT but no scripted-diff (Pieter Wuille) Tree-SHA512: 687b6c825f6f882f9c8e9d301bc893383710bad70216fa40b95f7e24d83a7148f9c759c3e4bd905a6cd26960829f8f6bd03106dc6c83ac312bf34ad239917018 --- contrib/devtools/commit-script-check.sh | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/contrib/devtools/commit-script-check.sh b/contrib/devtools/commit-script-check.sh index add4bb4883d4..1c9dbc7f68ff 100755 --- a/contrib/devtools/commit-script-check.sh +++ b/contrib/devtools/commit-script-check.sh @@ -20,20 +20,27 @@ RET=0 PREV_BRANCH=`git name-rev --name-only HEAD` PREV_HEAD=`git rev-parse HEAD` for i in `git rev-list --reverse $1`; do - git rev-list -n 1 --pretty="%s" $i | grep -q "^scripted-diff:" || continue - git checkout --quiet $i^ || exit - SCRIPT="`git rev-list --format=%b -n1 $i | sed '/^-BEGIN VERIFY SCRIPT-$/,/^-END VERIFY SCRIPT-$/{//!b};d'`" - if test "x$SCRIPT" = "x"; then - echo "Error: missing script for: $i" - echo "Failed" - RET=1 - else - echo "Running script for: $i" - echo "$SCRIPT" - eval "$SCRIPT" - git --no-pager diff --exit-code $i && echo "OK" || (echo "Failed"; false) || RET=1 + if git rev-list -n 1 --pretty="%s" $i | grep -q "^scripted-diff:"; then + git checkout --quiet $i^ || exit + SCRIPT="`git rev-list --format=%b -n1 $i | sed '/^-BEGIN VERIFY SCRIPT-$/,/^-END VERIFY SCRIPT-$/{//!b};d'`" + if test "x$SCRIPT" = "x"; then + echo "Error: missing script for: $i" + echo "Failed" + RET=1 + else + echo "Running script for: $i" + echo "$SCRIPT" + eval "$SCRIPT" + git --no-pager diff --exit-code $i && echo "OK" || (echo "Failed"; false) || RET=1 + fi + git reset --quiet --hard HEAD + else + if git rev-list "--format=%b" -n1 $i | grep -q '^-\(BEGIN\|END\)[ a-zA-Z]*-$'; then + echo "Error: script block marker but no scripted-diff in title" + echo "Failed" + RET=1 + fi fi - git reset --quiet --hard HEAD done git checkout --quiet $PREV_BRANCH 2>/dev/null || git checkout --quiet $PREV_HEAD exit $RET From 25008bd38a195ecdeafad33eb0a44d16991f94bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Thu, 1 Jun 2017 22:22:33 +0200 Subject: [PATCH 374/987] Small preparations for Q_FOREACH, PAIRTYPE and #include removal --- src/httprpc.cpp | 2 +- src/qt/platformstyle.cpp | 3 +-- src/utilstrencodings.h | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index ce64fb444dc9..28a6d9867e95 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -18,7 +18,7 @@ #include #include // boost::trim -#include //BOOST_FOREACH +#include /** WWW-Authenticate to present with 401 Unauthorized response */ static const char* WWW_AUTH_HEADER_DATA = "Basic realm=\"jsonrpc\""; diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index 06ecd38d260a..436c294f3c90 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -48,8 +48,7 @@ void MakeSingleColorImage(QImage& img, const QColor& colorbase) QIcon ColorizeIcon(const QIcon& ico, const QColor& colorbase) { QIcon new_ico; - QSize sz; - Q_FOREACH(sz, ico.availableSizes()) + Q_FOREACH(const QSize sz, ico.availableSizes()) { QImage img(ico.pixmap(sz).toImage()); MakeSingleColorImage(img, colorbase); diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index e4b6d6cf7cb1..082332a265eb 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -18,8 +18,6 @@ #define UBEGIN(a) ((unsigned char*)&(a)) #define UEND(a) ((unsigned char*)&((&(a))[1])) #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) - -/** This is needed because the foreach macro can't get over the comma in pair */ #define PAIRTYPE(t1, t2) std::pair /** Used by SanitizeString() */ From a15d7405e38e5845f91f890857c6a3135469c579 Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 5 Jul 2019 02:06:28 -0500 Subject: [PATCH 375/987] scripted diff: #10502 Fully remove BOOST_FOREACH -BEGIN VERIFY SCRIPT- sed -i 's/BOOST_FOREACH *(\(.*\),/for (\1 :/' ./src/*.h ./src/*.cpp ./src/*/*.h ./src/*/*.cpp ./src/*/*/*.h ./src/*/*/*.cpp ; -END VERIFY SCRIPT- --- src/bench/coin_selection.cpp | 2 +- src/bloom.cpp | 2 +- src/checkqueue.h | 4 +- src/core_write.cpp | 4 +- src/dash-tx.cpp | 2 +- src/httprpc.cpp | 2 +- src/init.cpp | 18 +++--- src/miner.cpp | 6 +- src/net.cpp | 62 +++++++++--------- src/net_processing.cpp | 36 +++++------ src/policy/policy.cpp | 4 +- src/qt/addresstablemodel.cpp | 2 +- src/qt/coincontroldialog.cpp | 6 +- src/qt/peertablemodel.cpp | 2 +- src/qt/recentrequeststablemodel.cpp | 2 +- src/qt/transactiondesc.cpp | 18 +++--- src/qt/transactionrecord.cpp | 4 +- src/qt/walletmodel.cpp | 12 ++-- src/rest.cpp | 6 +- src/rpc/blockchain.cpp | 20 +++--- src/rpc/mining.cpp | 2 +- src/rpc/misc.cpp | 2 +- src/rpc/net.cpp | 10 +-- src/rpc/rawtransaction.cpp | 8 +-- src/rpc/server.cpp | 6 +- src/script/ismine.cpp | 2 +- src/script/sign.cpp | 8 +-- src/script/standard.cpp | 4 +- src/sync.cpp | 10 +-- src/test/bip32_tests.cpp | 2 +- src/test/coins_tests.cpp | 2 +- src/test/getarg_tests.cpp | 2 +- src/test/multisig_tests.cpp | 2 +- src/test/prevector_tests.cpp | 4 +- src/test/script_tests.cpp | 4 +- src/test/test_dash.cpp | 2 +- src/test/transaction_tests.cpp | 2 +- src/timedata.cpp | 4 +- src/torcontrol.cpp | 6 +- src/txmempool.cpp | 54 ++++++++-------- src/validation.cpp | 26 ++++---- src/wallet/crypter.cpp | 2 +- src/wallet/db.cpp | 2 +- src/wallet/rpcdump.cpp | 4 +- src/wallet/rpcwallet.cpp | 34 +++++----- src/wallet/test/accounting_tests.cpp | 2 +- src/wallet/wallet.cpp | 96 ++++++++++++++-------------- src/wallet/walletdb.cpp | 10 +-- 48 files changed, 263 insertions(+), 263 deletions(-) diff --git a/src/bench/coin_selection.cpp b/src/bench/coin_selection.cpp index ec6e7a2c17b2..0e86568e5bf8 100644 --- a/src/bench/coin_selection.cpp +++ b/src/bench/coin_selection.cpp @@ -39,7 +39,7 @@ static void CoinSelection(benchmark::State& state) while (state.KeepRunning()) { // Empty wallet. - BOOST_FOREACH (COutput output, vCoins) + for (COutput output : vCoins) delete output.tx; vCoins.clear(); diff --git a/src/bloom.cpp b/src/bloom.cpp index 3f7a49c9fe1d..1a58b8714205 100644 --- a/src/bloom.cpp +++ b/src/bloom.cpp @@ -272,7 +272,7 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx) if (fFound) return true; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { // Match if the filter contains an outpoint tx spends if (contains(txin.prevout)) diff --git a/src/checkqueue.h b/src/checkqueue.h index 08017ff799c8..d7b7b836dcf2 100644 --- a/src/checkqueue.h +++ b/src/checkqueue.h @@ -120,7 +120,7 @@ class CCheckQueue fOk = fAllOk; } // execute work - BOOST_FOREACH (T& check, vChecks) + for (T& check : vChecks) if (fOk) fOk = check(); vChecks.clear(); @@ -150,7 +150,7 @@ class CCheckQueue void Add(std::vector& vChecks) { boost::unique_lock lock(mutex); - BOOST_FOREACH (T& check, vChecks) { + for (T& check : vChecks) { queue.push_back(T()); check.swap(queue.back()); } diff --git a/src/core_write.cpp b/src/core_write.cpp index 702f9b413ae7..edb60b55db55 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -146,7 +146,7 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey, out.pushKV("type", GetTxnOutputType(type)); UniValue a(UniValue::VARR); - BOOST_FOREACH(const CTxDestination& addr, addresses) + for (const CTxDestination& addr : addresses) a.push_back(CBitcoinAddress(addr).ToString()); out.pushKV("addresses", a); } @@ -160,7 +160,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry, entry.pushKV("locktime", (int64_t)tx.nLockTime); UniValue vin(UniValue::VARR); - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (const CTxIn& txin : tx.vin) { UniValue in(UniValue::VOBJ); if (tx.IsCoinBase()) in.pushKV("coinbase", HexStr(txin.scriptSig.begin(), txin.scriptSig.end())); diff --git a/src/dash-tx.cpp b/src/dash-tx.cpp index ee29754160ef..420a39a4aaef 100644 --- a/src/dash-tx.cpp +++ b/src/dash-tx.cpp @@ -585,7 +585,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr) SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); // ... and merge in other signatures: - BOOST_FOREACH(const CTransaction& txv, txVariants) { + for (const CTransaction& txv : txVariants) { txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig); } if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i))) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 28a6d9867e95..e0b943045ebb 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -94,7 +94,7 @@ static bool multiUserAuthorized(std::string strUserPass) if (gArgs.IsArgSet("-rpcauth")) { //Search for multi-user login/pass "rpcauth" from config - BOOST_FOREACH(std::string strRPCAuth, gArgs.GetArgs("-rpcauth")) + for (std::string strRPCAuth : gArgs.GetArgs("-rpcauth")) { std::vector vFields; boost::split(vFields, strRPCAuth, boost::is_any_of(":$")); diff --git a/src/init.cpp b/src/init.cpp index 242be406398f..f30e91b7e563 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -746,7 +746,7 @@ void CleanupBlockRevFiles() // keeping a separate counter. Once we hit a gap (or if 0 doesn't exist) // start removing block files. int nContigCounter = 0; - BOOST_FOREACH(const PAIRTYPE(std::string, fs::path)& item, mapBlockFiles) { + for (const PAIRTYPE(std::string, fs::path)& item : mapBlockFiles) { if (atoi(item.first) == nContigCounter) { nContigCounter++; continue; @@ -799,7 +799,7 @@ void ThreadImport(std::vector vImportFiles) } // -loadblock= - BOOST_FOREACH(const fs::path& path, vImportFiles) { + for (const fs::path& path : vImportFiles) { FILE *file = fsbridge::fopen(path, "rb"); if (file) { LogPrintf("Importing blocks file %s...\n", path.string()); @@ -1587,7 +1587,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } if (gArgs.IsArgSet("-uacomment")) { - BOOST_FOREACH(std::string cmt, gArgs.GetArgs("-uacomment")) + for (std::string cmt : gArgs.GetArgs("-uacomment")) { if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt)); @@ -1602,7 +1602,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) if (gArgs.IsArgSet("-onlynet")) { std::set nets; - BOOST_FOREACH(const std::string& snet, gArgs.GetArgs("-onlynet")) { + for (const std::string& snet : gArgs.GetArgs("-onlynet")) { enum Network net = ParseNetwork(snet); if (net == NET_UNROUTABLE) return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet)); @@ -1616,7 +1616,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } if (gArgs.IsArgSet("-whitelist")) { - BOOST_FOREACH(const std::string& net, gArgs.GetArgs("-whitelist")) { + for (const std::string& net : gArgs.GetArgs("-whitelist")) { CSubNet subnet; LookupSubNet(net.c_str(), subnet); if (!subnet.IsValid()) @@ -1678,7 +1678,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) if (fListen) { bool fBound = false; if (gArgs.IsArgSet("-bind")) { - BOOST_FOREACH(const std::string& strBind, gArgs.GetArgs("-bind")) { + for (const std::string& strBind : gArgs.GetArgs("-bind")) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) return InitError(ResolveErrMsg("bind", strBind)); @@ -1686,7 +1686,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } } if (gArgs.IsArgSet("-whitebind")) { - BOOST_FOREACH(const std::string& strBind, gArgs.GetArgs("-whitebind")) { + for (const std::string& strBind : gArgs.GetArgs("-whitebind")) { CService addrBind; if (!Lookup(strBind.c_str(), addrBind, 0, false)) return InitError(ResolveErrMsg("whitebind", strBind)); @@ -1706,7 +1706,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) } if (gArgs.IsArgSet("-externalip")) { - BOOST_FOREACH(const std::string& strAddr, gArgs.GetArgs("-externalip")) { + for (const std::string& strAddr : gArgs.GetArgs("-externalip")) { CService addrLocal; if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid()) AddLocal(addrLocal, LOCAL_MANUAL); @@ -2094,7 +2094,7 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) std::vector vImportFiles; if (gArgs.IsArgSet("-loadblock")) { - BOOST_FOREACH(const std::string& strFile, gArgs.GetArgs("-loadblock")) + for (const std::string& strFile : gArgs.GetArgs("-loadblock")) vImportFiles.push_back(strFile); } diff --git a/src/miner.cpp b/src/miner.cpp index 79218bc6221f..261052d77c44 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -275,7 +275,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, unsigned int packageSigOp // - safe TXs in regard to ChainLocks bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package) { - BOOST_FOREACH (const CTxMemPool::txiter it, package) { + for (const CTxMemPool::txiter it : package) { if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff)) return false; if (!llmq::chainLocksHandler->IsTxSafeForMining(it->GetTx().GetHash())) { @@ -308,11 +308,11 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already indexed_modified_transaction_set &mapModifiedTx) { int nDescendantsUpdated = 0; - BOOST_FOREACH(const CTxMemPool::txiter it, alreadyAdded) { + for (const CTxMemPool::txiter it : alreadyAdded) { CTxMemPool::setEntries descendants; mempool.CalculateDescendants(it, descendants); // Insert all descendants (not yet in block) into the modified set - BOOST_FOREACH(CTxMemPool::txiter desc, descendants) { + for (CTxMemPool::txiter desc : descendants) { if (alreadyAdded.count(desc)) continue; ++nDescendantsUpdated; diff --git a/src/net.cpp b/src/net.cpp index 8a8e94a17f99..ee12a26863d8 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -305,7 +305,7 @@ bool IsReachable(const CNetAddr& addr) CNode* CConnman::FindNode(const CNetAddr& ip) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if ((CNetAddr)pnode->addr == ip) return (pnode); return NULL; @@ -314,7 +314,7 @@ CNode* CConnman::FindNode(const CNetAddr& ip) CNode* CConnman::FindNode(const CSubNet& subNet) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if (subNet.Match((CNetAddr)pnode->addr)) return (pnode); return NULL; @@ -323,7 +323,7 @@ CNode* CConnman::FindNode(const CSubNet& subNet) CNode* CConnman::FindNode(const std::string& addrName) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) { + for (CNode* pnode : vNodes) { if (pnode->GetAddrName() == addrName) { return (pnode); } @@ -334,7 +334,7 @@ CNode* CConnman::FindNode(const std::string& addrName) CNode* CConnman::FindNode(const CService& addr) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) if((CService)pnode->addr == addr) return (pnode); return NULL; @@ -343,7 +343,7 @@ CNode* CConnman::FindNode(const CService& addr) bool CConnman::CheckIncomingNonce(uint64_t nonce) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) { + for (CNode* pnode : vNodes) { if (!pnode->fSuccessfullyConnected && !pnode->fInbound && pnode->GetLocalNonce() == nonce) return false; } @@ -537,7 +537,7 @@ void CConnman::Ban(const CSubNet& subNet, const BanReason &banReason, int64_t ba clientInterface->BannedListChanged(); { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) { + for (CNode* pnode : vNodes) { if (subNet.Match((CNetAddr)pnode->addr)) pnode->fDisconnect = true; } @@ -615,7 +615,7 @@ void CConnman::SetBannedSetDirty(bool dirty) bool CConnman::IsWhitelistedRange(const CNetAddr &addr) { LOCK(cs_vWhitelistedRange); - BOOST_FOREACH(const CSubNet& subnet, vWhitelistedRange) { + for (const CSubNet& subnet : vWhitelistedRange) { if (subnet.Match(addr)) return true; } @@ -986,7 +986,7 @@ bool CConnman::AttemptToEvictConnection() { LOCK(cs_vNodes); - BOOST_FOREACH(CNode *node, vNodes) { + for (CNode *node : vNodes) { if (node->fWhitelisted) continue; if (!node->fInbound) @@ -1066,7 +1066,7 @@ bool CConnman::AttemptToEvictConnection() unsigned int nMostConnections = 0; int64_t nMostConnectionsTime = 0; std::map > mapNetGroupNodes; - BOOST_FOREACH(const NodeEvictionCandidate &node, vEvictionCandidates) { + for (const NodeEvictionCandidate &node : vEvictionCandidates) { mapNetGroupNodes[node.nKeyedNetGroup].push_back(node); int64_t grouptime = mapNetGroupNodes[node.nKeyedNetGroup][0].nTimeConnected; size_t groupsize = mapNetGroupNodes[node.nKeyedNetGroup].size(); @@ -1111,7 +1111,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) { bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr); { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) { + for (CNode* pnode : vNodes) { if (pnode->fInbound) { nInbound++; if (!pnode->verifiedProRegTxHash.IsNull()) { @@ -1206,7 +1206,7 @@ void CConnman::ThreadSocketHandler() LOCK(cs_vNodes); // Disconnect unused nodes std::vector vNodesCopy = vNodes; - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) { if (pnode->fDisconnect) { @@ -1232,7 +1232,7 @@ void CConnman::ThreadSocketHandler() { // Delete disconnected nodes std::list vNodesDisconnectedCopy = vNodesDisconnected; - BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy) + for (CNode* pnode : vNodesDisconnectedCopy) { // wait until threads are done using it if (pnode->GetRefCount() <= 0) { @@ -1292,7 +1292,7 @@ void CConnman::ThreadSocketHandler() have_fds = true; #endif - BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) { + for (const ListenSocket& hListenSocket : vhListenSocket) { FD_SET(hListenSocket.socket, &fdsetRecv); hSocketMax = std::max(hSocketMax, hListenSocket.socket); have_fds = true; @@ -1300,7 +1300,7 @@ void CConnman::ThreadSocketHandler() { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) { // Implement the following logic: // * If there is data to send, select() for sending data. As this only @@ -1377,7 +1377,7 @@ void CConnman::ThreadSocketHandler() // // Accept new connections // - BOOST_FOREACH(const ListenSocket& hListenSocket, vhListenSocket) + for (const ListenSocket& hListenSocket : vhListenSocket) { if (hListenSocket.socket != INVALID_SOCKET && FD_ISSET(hListenSocket.socket, &fdsetRecv)) { @@ -1389,7 +1389,7 @@ void CConnman::ThreadSocketHandler() // Service each socket // std::vector vNodesCopy = CopyNodeVector(); - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) { if (interruptNet) return; @@ -1703,7 +1703,7 @@ void CConnman::ThreadDNSAddressSeed() LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); - BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) { + for (const CDNSSeedData &seed : vSeeds) { if (interruptNet) { return; } @@ -1715,7 +1715,7 @@ void CConnman::ThreadDNSAddressSeed() ServiceFlags requiredServiceBits = nRelevantServices; if (LookupHost(GetDNSHost(seed, &requiredServiceBits).c_str(), vIPs, 0, true)) { - BOOST_FOREACH(const CNetAddr& ip, vIPs) + for (const CNetAddr& ip : vIPs) { int nOneDay = 24*3600; CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits); @@ -1796,7 +1796,7 @@ void CConnman::ThreadOpenConnections() for (int64_t nLoop = 0;; nLoop++) { ProcessOneShot(); - BOOST_FOREACH(const std::string& strAddr, gArgs.GetArgs("-connect")) + for (const std::string& strAddr : gArgs.GetArgs("-connect")) { CAddress addr(CService(), NODE_NONE); OpenNetworkConnection(addr, false, NULL, strAddr.c_str()); @@ -1852,7 +1852,7 @@ void CConnman::ThreadOpenConnections() std::set > setConnected; if (!Params().AllowMultipleAddressesFromGroup()) { LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) { + for (CNode* pnode : vNodes) { if (!pnode->fInbound && !pnode->fAddnode && !pnode->fMasternode) { // Count the peers that have all relevant services @@ -1978,7 +1978,7 @@ std::vector CConnman::GetAddedNodeInfo() { LOCK(cs_vAddedNodes); ret.reserve(vAddedNodes.size()); - BOOST_FOREACH(const std::string& strAddNode, vAddedNodes) + for (const std::string& strAddNode : vAddedNodes) lAddresses.push_back(strAddNode); } @@ -1999,7 +1999,7 @@ std::vector CConnman::GetAddedNodeInfo() } } - BOOST_FOREACH(const std::string& strAddNode, lAddresses) { + for (const std::string& strAddNode : lAddresses) { CService service(LookupNumeric(strAddNode.c_str(), Params().GetDefaultPort())); if (service.IsValid()) { // strAddNode is an IP:port @@ -2203,7 +2203,7 @@ void CConnman::ThreadMessageHandler() bool fMoreWork = false; - BOOST_FOREACH(CNode* pnode, vNodesCopy) + for (CNode* pnode : vNodesCopy) { if (pnode->fDisconnect) continue; @@ -2349,7 +2349,7 @@ void Discover(boost::thread_group& threadGroup) std::vector vaddr; if (LookupHost(pszHostName, vaddr, 0, true)) { - BOOST_FOREACH (const CNetAddr &addr, vaddr) + for (const CNetAddr &addr : vaddr) { if (AddLocal(addr, LOCAL_IF)) LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString()); @@ -2396,7 +2396,7 @@ void CConnman::SetNetworkActive(bool active) LOCK(cs_vNodes); // Close sockets to all nodes - BOOST_FOREACH(CNode* pnode, vNodes) { + for (CNode* pnode : vNodes) { pnode->CloseSocketDisconnect(); } } else { @@ -2642,18 +2642,18 @@ void CConnman::Stop() } // Close sockets - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) pnode->CloseSocketDisconnect(); - BOOST_FOREACH(ListenSocket& hListenSocket, vhListenSocket) + for (ListenSocket& hListenSocket : vhListenSocket) if (hListenSocket.socket != INVALID_SOCKET) if (!CloseSocket(hListenSocket.socket)) LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError())); // clean up some globals (to help leak detection) - BOOST_FOREACH(CNode *pnode, vNodes) { + for (CNode *pnode : vNodes) { DeleteNode(pnode); } - BOOST_FOREACH(CNode *pnode, vNodesDisconnected) { + for (CNode *pnode : vNodesDisconnected) { DeleteNode(pnode); } vNodes.clear(); @@ -2894,7 +2894,7 @@ void CConnman::RelayTransaction(const CTransaction& tx) } CInv inv(nInv, hash); LOCK(cs_vNodes); - BOOST_FOREACH(CNode* pnode, vNodes) + for (CNode* pnode : vNodes) { pnode->PushInventory(inv); } @@ -3135,7 +3135,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn fPauseSend = false; nProcessQueueSize = 0; - BOOST_FOREACH(const std::string &msg, getAllNetMessageTypes()) + for (const std::string &msg : getAllNetMessageTypes()) mapRecvBytesPerMsgCmd[msg] = 0; mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index da1c2232c709..2488178ace45 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -323,7 +323,7 @@ void FinalizeNode(NodeId nodeid, bool& fUpdateConnectionTime) { fUpdateConnectionTime = true; } - BOOST_FOREACH(const QueuedBlock& entry, state->vBlocksInFlight) { + for (const QueuedBlock& entry : state->vBlocksInFlight) { mapBlocksInFlight.erase(entry.hash); } EraseOrphansFor(nodeid); @@ -558,7 +558,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vectorIsValid(BLOCK_VALID_TREE)) { // We consider the chain that this peer is on invalid. return; @@ -598,7 +598,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) { stats.nMisbehavior = state->nMisbehavior; stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1; stats.nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1; - BOOST_FOREACH(const QueuedBlock& queue, state->vBlocksInFlight) { + for (const QueuedBlock& queue : state->vBlocksInFlight) { if (queue.pindex) stats.vHeightInFlight.push_back(queue.pindex->nHeight); } @@ -659,7 +659,7 @@ bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRE auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer, GetTime() + ORPHAN_TX_EXPIRE_TIME}); assert(ret.second); - BOOST_FOREACH(const CTxIn& txin, tx->vin) { + for (const CTxIn& txin : tx->vin) { mapOrphanTransactionsByPrev[txin.prevout].insert(ret.first); } @@ -675,7 +675,7 @@ int static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(g_cs_orphans) std::map::iterator it = mapOrphanTransactions.find(hash); if (it == mapOrphanTransactions.end()) return 0; - BOOST_FOREACH(const CTxIn& txin, it->second.tx->vin) + for (const CTxIn& txin : it->second.tx->vin) { auto itPrev = mapOrphanTransactionsByPrev.find(txin.prevout); if (itPrev == mapOrphanTransactionsByPrev.end()) @@ -826,7 +826,7 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr& pb // Erase orphan transactions include or precluded by this block if (vOrphanErase.size()) { int nErased = 0; - BOOST_FOREACH(uint256 &orphanHash, vOrphanErase) { + for (uint256 &orphanHash : vOrphanErase) { nErased += EraseOrphanTx(orphanHash); } LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased); @@ -1147,7 +1147,7 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus // Thus, the protocol spec specified allows for us to provide duplicate txn here, // however we MUST always provide at least what the remote peer needs typedef std::pair PairType; - BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn) + for (PairType& pair : merkleBlock.vMatchedTxn) connman.PushMessage(pfrom, msgMaker.Make(NetMsgType::TX, *pblock->vtx[pair.first])); } // else @@ -1708,7 +1708,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr std::vector vAddrOk; int64_t nNow = GetAdjustedTime(); int64_t nSince = nNow - 10 * 60; - BOOST_FOREACH(CAddress& addr, vAddr) + for (CAddress& addr : vAddr) { if (interruptMsgProc) return true; @@ -2216,20 +2216,20 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } } - BOOST_FOREACH(uint256 hash, vEraseQueue) + for (uint256 hash : vEraseQueue) EraseOrphanTx(hash); } else if (fMissingInputs) { bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (const CTxIn& txin : tx.vin) { if (recentRejects->contains(txin.prevout.hash)) { fRejectedParents = true; break; } } if (!fRejectedParents) { - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (const CTxIn& txin : tx.vin) { CInv _inv(MSG_TX, txin.prevout.hash); pfrom->AddInventoryKnown(_inv); if (!AlreadyHave(_inv)) pfrom->AskFor(_inv); @@ -2748,7 +2748,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->vAddrToSend.clear(); std::vector vAddr = connman.GetAddresses(); FastRandomContext insecure_rand; - BOOST_FOREACH(const CAddress &addr, vAddr) + for (const CAddress &addr : vAddr) pfrom->PushAddress(addr, insecure_rand); } @@ -2944,7 +2944,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr else { bool found = false; const std::vector &allMessages = getAllNetMessageTypes(); - BOOST_FOREACH(const std::string msg, allMessages) { + for (const std::string msg : allMessages) { if(msg == strCommand) { found = true; break; @@ -2984,7 +2984,7 @@ static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman& connman) AssertLockHeld(cs_main); CNodeState &state = *State(pnode->GetId()); - BOOST_FOREACH(const CBlockReject& reject, state.rejects) { + for (const CBlockReject& reject : state.rejects) { connman.PushMessage(pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, (std::string)NetMsgType::BLOCK, reject.chRejectCode, reject.strRejectReason, reject.hashBlock)); } state.rejects.clear(); @@ -3205,7 +3205,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr pto->nNextAddrSend = PoissonNextSend(nNow, AVG_ADDRESS_BROADCAST_INTERVAL); std::vector vAddr; vAddr.reserve(pto->vAddrToSend.size()); - BOOST_FOREACH(const CAddress& addr, pto->vAddrToSend) + for (const CAddress& addr : pto->vAddrToSend) { if (!pto->addrKnown.contains(addr.GetKey())) { @@ -3284,7 +3284,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr // Try to find first header that our peer doesn't have, and // then send all headers past that one. If we come across any // headers that aren't on chainActive, give up. - BOOST_FOREACH(const uint256 &hash, pto->vBlockHashesToAnnounce) { + for (const uint256 &hash : pto->vBlockHashesToAnnounce) { BlockMap::iterator mi = mapBlockIndex.find(hash); assert(mi != mapBlockIndex.end()); const CBlockIndex *pindex = mi->second; @@ -3412,7 +3412,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr vInv.reserve(std::max(pto->vInventoryBlockToSend.size(), INVENTORY_BROADCAST_MAX_PER_1MB_BLOCK * MaxBlockSize(true) / 1000000)); // Add blocks - BOOST_FOREACH(const uint256& hash, pto->vInventoryBlockToSend) { + for (const uint256& hash : pto->vInventoryBlockToSend) { vInv.push_back(CInv(MSG_BLOCK, hash)); if (vInv.size() == MAX_INV_SZ) { connman.PushMessage(pto, msgMaker.Make(NetMsgType::INV, vInv)); @@ -3606,7 +3606,7 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic& interr std::vector vToDownload; NodeId staller = -1; FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams); - BOOST_FOREACH(const CBlockIndex *pindex, vToDownload) { + for (const CBlockIndex *pindex : vToDownload) { vGetData.push_back(CInv(MSG_BLOCK, pindex->GetBlockHash())); MarkBlockAsInFlight(pto->GetId(), pindex->GetBlockHash(), pindex); LogPrint(BCLog::NET, "Requesting block %s (%d) peer=%d\n", pindex->GetBlockHash().ToString(), diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 1b1b30017f97..cf07968e15df 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -92,7 +92,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) return false; } - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed // keys (remember the 520 byte limit on redeemScript size). That works @@ -113,7 +113,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason) unsigned int nDataOut = 0; txnouttype whichType; - BOOST_FOREACH(const CTxOut& txout, tx.vout) { + for (const CTxOut& txout : tx.vout) { if (!::IsStandard(txout.scriptPubKey, whichType)) { reason = "scriptpubkey"; return false; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 61a024ded318..7f452faee6db 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -82,7 +82,7 @@ class AddressTablePriv cachedAddressTable.clear(); { LOCK(wallet->cs_wallet); - BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook) + for (const PAIRTYPE(CTxDestination, CAddressBookData)& item : wallet->mapAddressBook) { const CBitcoinAddress& address = item.first; bool fMine = IsMine(*wallet, address.Get()); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index f6c47e025fdc..e96c313c90a5 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -504,7 +504,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) coinControl->ListSelected(vCoinControl); model->getOutputs(vCoinControl, vOutputs); - BOOST_FOREACH(const COutput& out, vOutputs) { + for (const COutput& out : vOutputs) { // unselect already spent, very unlikely scenario, this could happen // when selected are spent elsewhere, like rpc or another computer uint256 txhash = out.tx->GetHash(); @@ -672,7 +672,7 @@ void CoinControlDialog::updateView() std::map > mapCoins; model->listCoins(mapCoins); - BOOST_FOREACH(const PAIRTYPE(QString, std::vector)& coins, mapCoins) { + for (const PAIRTYPE(QString, std::vector)& coins : mapCoins) { CCoinControlWidgetItem *itemWalletAddress = new CCoinControlWidgetItem(); itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); QString sWalletAddress = coins.first; @@ -699,7 +699,7 @@ void CoinControlDialog::updateView() CAmount nSum = 0; int nChildren = 0; - BOOST_FOREACH(const COutput& out, coins.second) { + for (const COutput& out : coins.second) { nSum += out.tx->tx->vout[out.i].nValue; nChildren++; diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 33b1f611f86f..6f4eb86a3632 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -79,7 +79,7 @@ class PeerTablePriv TRY_LOCK(cs_main, lockMain); if (lockMain) { - BOOST_FOREACH(CNodeCombinedStats &stats, cachedNodeStats) + for (CNodeCombinedStats &stats : cachedNodeStats) stats.fNodeStateStatsAvailable = GetNodeStateStats(stats.nodeStats.nodeid, stats.nodeStateStats); } } diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp index fd57b494abd6..e1850983535a 100644 --- a/src/qt/recentrequeststablemodel.cpp +++ b/src/qt/recentrequeststablemodel.cpp @@ -22,7 +22,7 @@ RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel // Load entries from wallet std::vector vReceiveRequests; parent->loadReceiveRequests(vReceiveRequests); - BOOST_FOREACH(const std::string& request, vReceiveRequests) + for (const std::string& request : vReceiveRequests) addNewRequest(request); /* These columns must match the indices in the ColumnIndex enumeration */ diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 8a495eddc1a7..3a1f395dd769 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -149,7 +149,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // Coinbase // CAmount nUnmatured = 0; - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for (const CTxOut& txout : wtx.tx->vout) nUnmatured += wallet->GetCredit(txout, ISMINE_ALL); strHTML += "" + tr("Credit") + ": "; if (wtx.IsInMainChain()) @@ -168,14 +168,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco else { isminetype fAllFromMe = ISMINE_SPENDABLE; - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) { isminetype mine = wallet->IsMine(txin); if(fAllFromMe > mine) fAllFromMe = mine; } isminetype fAllToMe = ISMINE_SPENDABLE; - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for (const CTxOut& txout : wtx.tx->vout) { isminetype mine = wallet->IsMine(txout); if(fAllToMe > mine) fAllToMe = mine; @@ -189,7 +189,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // // Debit // - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for (const CTxOut& txout : wtx.tx->vout) { // Ignore change isminetype toSelf = wallet->IsMine(txout); @@ -237,10 +237,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // // Mixed debit transaction // - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) if (wallet->IsMine(txin)) strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
"; - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for (const CTxOut& txout : wtx.tx->vout) if (wallet->IsMine(txout)) strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
"; } @@ -292,10 +292,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (logCategories != BCLog::NONE) { strHTML += "

" + tr("Debug information") + "

"; - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) if(wallet->IsMine(txin)) strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
"; - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for (const CTxOut& txout : wtx.tx->vout) if(wallet->IsMine(txout)) strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
"; @@ -305,7 +305,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "
" + tr("Inputs") + ":"; strHTML += "
    "; - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) { COutPoint prevout = txin.prevout; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index fb78a17f9c26..7fde2aa4349e 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -83,7 +83,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * int nFromMe = 0; bool involvesWatchAddress = false; isminetype fAllFromMe = ISMINE_SPENDABLE; - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) { if(wallet->IsMine(txin)) { fAllFromMeDenom = fAllFromMeDenom && wallet->IsDenominated(txin.prevout); @@ -97,7 +97,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * isminetype fAllToMe = ISMINE_SPENDABLE; bool fAllToMeDenom = true; int nToMe = 0; - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) { + for (const CTxOut& txout : wtx.tx->vout) { if(wallet->IsMine(txout)) { fAllToMeDenom = fAllToMeDenom && CPrivateSend::IsDenominatedAmount(txout.nValue); nToMe++; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 71b3b37b2a3d..b621202459b1 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -79,7 +79,7 @@ CAmount WalletModel::getBalance(const CCoinControl *coinControl) const CAmount nBalance = 0; std::vector vCoins; wallet->AvailableCoins(vCoins, true, coinControl); - BOOST_FOREACH(const COutput& out, vCoins) + for (const COutput& out : vCoins) if(out.fSpendable) nBalance += out.tx->tx->vout[out.i].nValue; @@ -681,7 +681,7 @@ bool WalletModel::getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const void WalletModel::getOutputs(const std::vector& vOutpoints, std::vector& vOutputs) { LOCK2(cs_main, wallet->cs_wallet); - BOOST_FOREACH(const COutPoint& outpoint, vOutpoints) + for (const COutPoint& outpoint : vOutpoints) { if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); @@ -708,7 +708,7 @@ void WalletModel::listCoins(std::map >& mapCoins) wallet->ListLockedCoins(vLockedCoins); // add locked coins - BOOST_FOREACH(const COutPoint& outpoint, vLockedCoins) + for (const COutPoint& outpoint : vLockedCoins) { if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); @@ -718,7 +718,7 @@ void WalletModel::listCoins(std::map >& mapCoins) vCoins.push_back(out); } - BOOST_FOREACH(const COutput& out, vCoins) + for (const COutput& out : vCoins) { COutput cout = out; @@ -768,8 +768,8 @@ void WalletModel::listProTxCoins(std::vector& vOutpts) void WalletModel::loadReceiveRequests(std::vector& vReceiveRequests) { LOCK(wallet->cs_wallet); - BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook) - BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item2, item.second.destdata) + for (const PAIRTYPE(CTxDestination, CAddressBookData)& item : wallet->mapAddressBook) + for (const PAIRTYPE(std::string, std::string)& item2 : item.second.destdata) if (item2.first.size() > 2 && item2.first.substr(0,2) == "rr") // receive request vReceiveRequests.push_back(item2.second); } diff --git a/src/rest.cpp b/src/rest.cpp index 7bca7488e95c..69220579269d 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -158,7 +158,7 @@ static bool rest_headers(HTTPRequest* req, } CDataStream ssHeader(SER_NETWORK, PROTOCOL_VERSION); - BOOST_FOREACH(const CBlockIndex *pindex, headers) { + for (const CBlockIndex *pindex : headers) { ssHeader << pindex->GetBlockHeader(); } @@ -178,7 +178,7 @@ static bool rest_headers(HTTPRequest* req, } case RF_JSON: { UniValue jsonHeaders(UniValue::VARR); - BOOST_FOREACH(const CBlockIndex *pindex, headers) { + for (const CBlockIndex *pindex : headers) { jsonHeaders.push_back(blockheaderToJSON(pindex)); } std::string strJSON = jsonHeaders.write() + "\n"; @@ -558,7 +558,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) objGetUTXOResponse.push_back(Pair("bitmap", bitmapStringRepresentation)); UniValue utxos(UniValue::VARR); - BOOST_FOREACH (const CCoin& coin, outs) { + for (const CCoin& coin : outs) { UniValue utxo(UniValue::VOBJ); utxo.push_back(Pair("height", (int32_t)coin.nHeight)); utxo.push_back(Pair("value", ValueFromAmount(coin.out.nValue))); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 7806f425ae3a..a5350626e0ee 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -387,14 +387,14 @@ void entryToJSON(UniValue &info, const CTxMemPoolEntry &e) info.push_back(Pair("ancestorfees", e.GetModFeesWithAncestors())); const CTransaction& tx = e.GetTx(); std::set setDepends; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { if (mempool.exists(txin.prevout.hash)) setDepends.insert(txin.prevout.hash.ToString()); } UniValue depends(UniValue::VARR); - BOOST_FOREACH(const std::string& dep, setDepends) + for (const std::string& dep : setDepends) { depends.push_back(dep); } @@ -409,7 +409,7 @@ UniValue mempoolToJSON(bool fVerbose) { LOCK(mempool.cs); UniValue o(UniValue::VOBJ); - BOOST_FOREACH(const CTxMemPoolEntry& e, mempool.mapTx) + for (const CTxMemPoolEntry& e : mempool.mapTx) { const uint256& hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); @@ -424,7 +424,7 @@ UniValue mempoolToJSON(bool fVerbose) mempool.queryHashes(vtxid); UniValue a(UniValue::VARR); - BOOST_FOREACH(const uint256& hash, vtxid) + for (const uint256& hash : vtxid) a.push_back(hash.ToString()); return a; @@ -509,14 +509,14 @@ UniValue getmempoolancestors(const JSONRPCRequest& request) if (!fVerbose) { UniValue o(UniValue::VARR); - BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) { + for (CTxMemPool::txiter ancestorIt : setAncestors) { o.push_back(ancestorIt->GetTx().GetHash().ToString()); } return o; } else { UniValue o(UniValue::VOBJ); - BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) { + for (CTxMemPool::txiter ancestorIt : setAncestors) { const CTxMemPoolEntry &e = *ancestorIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); @@ -573,14 +573,14 @@ UniValue getmempooldescendants(const JSONRPCRequest& request) if (!fVerbose) { UniValue o(UniValue::VARR); - BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) { + for (CTxMemPool::txiter descendantIt : setDescendants) { o.push_back(descendantIt->GetTx().GetHash().ToString()); } return o; } else { UniValue o(UniValue::VOBJ); - BOOST_FOREACH(CTxMemPool::txiter descendantIt, setDescendants) { + for (CTxMemPool::txiter descendantIt : setDescendants) { const CTxMemPoolEntry &e = *descendantIt; const uint256& _hash = e.GetTx().GetHash(); UniValue info(UniValue::VOBJ); @@ -1512,7 +1512,7 @@ UniValue getchaintips(const JSONRPCRequest& request) std::set setOrphans; std::set setPrevs; - BOOST_FOREACH(const PAIRTYPE(const uint256, CBlockIndex*)& item, mapBlockIndex) + for (const PAIRTYPE(const uint256, CBlockIndex*)& item : mapBlockIndex) { if (!chainActive.Contains(item.second)) { setOrphans.insert(item.second); @@ -1541,7 +1541,7 @@ UniValue getchaintips(const JSONRPCRequest& request) /* Construct the output array. */ UniValue res(UniValue::VARR); - BOOST_FOREACH(const CBlockIndex* block, setTips) + for (const CBlockIndex* block : setTips) { const CBlockIndex* pindexFork = chainActive.FindFork(block); const int branchLen = block->nHeight - pindexFork->nHeight; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 00ae7a059350..f4ef6cebd593 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -601,7 +601,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) entry.push_back(Pair("hash", txHash.GetHex())); UniValue deps(UniValue::VARR); - BOOST_FOREACH (const CTxIn &in, tx.vin) + for (const CTxIn &in : tx.vin) { if (setTxIndex.count(in.prevout.hash)) deps.push_back(setTxIndex[in.prevout.hash]); diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 41fda5f9b284..ef886dbc1b7c 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -232,7 +232,7 @@ class DescribeAddressVisitor : public boost::static_visitor obj.push_back(Pair("script", GetTxnOutputType(whichType))); obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); UniValue a(UniValue::VARR); - BOOST_FOREACH(const CTxDestination& addr, addresses) + for (const CTxDestination& addr : addresses) a.push_back(CBitcoinAddress(addr).ToString()); obj.push_back(Pair("addresses", a)); if (whichType == TX_MULTISIG) diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 3d31b52d5091..4f94b2cfd616 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -127,7 +127,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) UniValue ret(UniValue::VARR); - BOOST_FOREACH(const CNodeStats& stats, vstats) { + for (const CNodeStats& stats : vstats) { UniValue obj(UniValue::VOBJ); CNodeStateStats statestats; bool fStateStats = GetNodeStateStats(stats.nodeid, statestats); @@ -164,7 +164,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) obj.push_back(Pair("synced_headers", statestats.nSyncHeight)); obj.push_back(Pair("synced_blocks", statestats.nCommonHeight)); UniValue heights(UniValue::VARR); - BOOST_FOREACH(int height, statestats.vHeightInFlight) { + for (int height : statestats.vHeightInFlight) { heights.push_back(height); } obj.push_back(Pair("inflight", heights)); @@ -172,14 +172,14 @@ UniValue getpeerinfo(const JSONRPCRequest& request) obj.push_back(Pair("whitelisted", stats.fWhitelisted)); UniValue sendPerMsgCmd(UniValue::VOBJ); - BOOST_FOREACH(const mapMsgCmdSize::value_type &i, stats.mapSendBytesPerMsgCmd) { + for (const mapMsgCmdSize::value_type &i : stats.mapSendBytesPerMsgCmd) { if (i.second > 0) sendPerMsgCmd.push_back(Pair(i.first, i.second)); } obj.push_back(Pair("bytessent_per_msg", sendPerMsgCmd)); UniValue recvPerMsgCmd(UniValue::VOBJ); - BOOST_FOREACH(const mapMsgCmdSize::value_type &i, stats.mapRecvBytesPerMsgCmd) { + for (const mapMsgCmdSize::value_type &i : stats.mapRecvBytesPerMsgCmd) { if (i.second > 0) recvPerMsgCmd.push_back(Pair(i.first, i.second)); } @@ -475,7 +475,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request) UniValue localAddresses(UniValue::VARR); { LOCK(cs_mapLocalHost); - BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost) + for (const PAIRTYPE(CNetAddr, LocalServiceInfo) &item : mapLocalHost) { UniValue rec(UniValue::VOBJ); rec.push_back(Pair("address", item.first.ToString())); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index e5b7d64a06ec..676a9521b7e6 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -332,7 +332,7 @@ UniValue verifytxoutproof(const JSONRPCRequest& request) if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()])) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain"); - BOOST_FOREACH(const uint256& hash, vMatch) + for (const uint256& hash : vMatch) res.push_back(hash.GetHex()); return res; } @@ -423,7 +423,7 @@ UniValue createrawtransaction(const JSONRPCRequest& request) std::set setAddress; std::vector addrList = sendTo.getKeys(); - BOOST_FOREACH(const std::string& name_, addrList) { + for (const std::string& name_ : addrList) { if (name_ == "data") { std::vector data = ParseHexV(sendTo[name_].getValStr(),"Data"); @@ -682,7 +682,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) CCoinsViewMemPool viewMempool(&viewChain, mempool); view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view - BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) { + for (const CTxIn& txin : mergedTx.vin) { view.AccessCoin(txin.prevout); // Load entries from viewChain into view; can fail. } @@ -821,7 +821,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request) SignSignature(keystore, prevPubKey, mergedTx, i, nHashType); // ... and merge in other signatures: - BOOST_FOREACH(const CMutableTransaction& txv, txVariants) { + for (const CMutableTransaction& txv : txVariants) { if (txv.vin.size() > i) { txin.scriptSig = CombineSignatures(prevPubKey, txConst, i, txin.scriptSig, txv.vin[i].scriptSig); } diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 8eb15d315319..5a41a12d8fb0 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -64,7 +64,7 @@ void RPCTypeCheck(const UniValue& params, bool fAllowNull) { unsigned int i = 0; - BOOST_FOREACH(UniValue::VType t, typesExpected) + for (UniValue::VType t : typesExpected) { if (params.size() <= i) break; @@ -103,7 +103,7 @@ void RPCTypeCheckObj(const UniValue& o, if (fStrict) { - BOOST_FOREACH(const std::string& k, o.getKeys()) + for (const std::string& k : o.getKeys()) { if (typesExpected.count(k) == 0) { @@ -233,7 +233,7 @@ std::string CRPCTable::help(const std::string& strCommand, const std::string& st jreq.fHelp = true; jreq.params = UniValue(); - BOOST_FOREACH(const PAIRTYPE(std::string, const CRPCCommand*)& command, vCommands) + for (const PAIRTYPE(std::string, const CRPCCommand*)& command : vCommands) { const CRPCCommand *pcmd = command.second; std::string strMethod = pcmd->name; diff --git a/src/script/ismine.cpp b/src/script/ismine.cpp index a66e79bef17f..fe9215c67da2 100644 --- a/src/script/ismine.cpp +++ b/src/script/ismine.cpp @@ -18,7 +18,7 @@ typedef std::vector valtype; unsigned int HaveKeys(const std::vector& pubkeys, const CKeyStore& keystore) { unsigned int nResult = 0; - BOOST_FOREACH(const valtype& pubkey, pubkeys) + for (const valtype& pubkey : pubkeys) { CKeyID keyID = CPubKey(pubkey).GetID(); if (keystore.HaveKey(keyID)) diff --git a/src/script/sign.cpp b/src/script/sign.cpp index c945972a44fa..9e4424e7c8a9 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -148,7 +148,7 @@ bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutab static CScript PushAll(const std::vector& values) { CScript result; - BOOST_FOREACH(const valtype& v, values) + for (const valtype& v : values) result << v; return result; } @@ -159,12 +159,12 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC { // Combine all the signatures we've got: std::set allsigs; - BOOST_FOREACH(const valtype& v, sigs1) + for (const valtype& v : sigs1) { if (!v.empty()) allsigs.insert(v); } - BOOST_FOREACH(const valtype& v, sigs2) + for (const valtype& v : sigs2) { if (!v.empty()) allsigs.insert(v); @@ -175,7 +175,7 @@ static CScript CombineMultisig(const CScript& scriptPubKey, const BaseSignatureC unsigned int nSigsRequired = vSolutions.front()[0]; unsigned int nPubKeys = vSolutions.size()-2; std::map sigs; - BOOST_FOREACH(const valtype& sig, allsigs) + for (const valtype& sig : allsigs) { for (unsigned int i = 0; i < nPubKeys; i++) { diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 616b30cca948..128513f654f4 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -76,7 +76,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& keys) CScript script; script << CScript::EncodeOP_N(nRequired); - BOOST_FOREACH(const CPubKey& key, keys) + for (const CPubKey& key : keys) script << ToByteVector(key); script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; return script; diff --git a/src/sync.cpp b/src/sync.cpp index 924223630ee8..092b8df17f5f 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -77,7 +77,7 @@ static void potential_deadlock_detected(const std::pair& mismatch, std::string strOutput = ""; strOutput += "POTENTIAL DEADLOCK DETECTED\n"; strOutput += "Previous lock order was:\n"; - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s2) { + for (const PAIRTYPE(void*, CLockLocation) & i : s2) { if (i.first == mismatch.first) { strOutput += " (1)"; } @@ -87,7 +87,7 @@ static void potential_deadlock_detected(const std::pair& mismatch, strOutput += strprintf(" %s\n", i.second.ToString().c_str()); } strOutput += "Current lock order is:\n"; - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, s1) { + for (const PAIRTYPE(void*, CLockLocation) & i : s1) { if (i.first == mismatch.first) { strOutput += " (1)"; } @@ -112,7 +112,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) (*lockstack).push_back(std::make_pair(c, locklocation)); - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, (*lockstack)) { + for (const PAIRTYPE(void*, CLockLocation) & i : (*lockstack)) { if (i.first == c) break; @@ -146,14 +146,14 @@ void LeaveCritical() std::string LocksHeld() { std::string result; - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) + for (const PAIRTYPE(void*, CLockLocation) & i : *lockstack) result += i.second.ToString() + std::string("\n"); return result; } void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) { - BOOST_FOREACH (const PAIRTYPE(void*, CLockLocation) & i, *lockstack) + for (const PAIRTYPE(void*, CLockLocation) & i : *lockstack) if (i.first == cs) return; fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 402aef27a0e6..ab040c5cc7f4 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -93,7 +93,7 @@ void RunTest(const TestVector &test) { CExtPubKey pubkey; key.SetMaster(&seed[0], seed.size()); pubkey = key.Neuter(); - BOOST_FOREACH(const TestDerivation &derive, test.vDerive) { + for (const TestDerivation &derive : test.vDerive) { unsigned char data[74]; key.Encode(data); pubkey.Encode(data); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index f6e8adab802c..58f77731b4e9 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(coins_cache_simulation_test) found_an_entry = true; } } - BOOST_FOREACH(const CCoinsViewCacheTest *test, stack) { + for (const CCoinsViewCacheTest *test : stack) { test->SelfTest(); } } diff --git a/src/test/getarg_tests.cpp b/src/test/getarg_tests.cpp index b9ce280d047b..28bec6374a29 100644 --- a/src/test/getarg_tests.cpp +++ b/src/test/getarg_tests.cpp @@ -25,7 +25,7 @@ static void ResetArgs(const std::string& strArg) // Convert to char*: std::vector vecChar; - BOOST_FOREACH(std::string& s, vecArg) + for (std::string& s : vecArg) vecChar.push_back(s.c_str()); gArgs.ParseParameters(vecChar.size(), &vecChar[0]); diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 2c2f76323813..d1dc6ed8058b 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -28,7 +28,7 @@ sign_multisig(CScript scriptPubKey, std::vector keys, CTransaction transac CScript result; result << OP_0; // CHECKMULTISIG bug workaround - BOOST_FOREACH(const CKey &key, keys) + for (const CKey &key : keys) { std::vector vchSig; BOOST_CHECK(key.Sign(hash, vchSig)); diff --git a/src/test/prevector_tests.cpp b/src/test/prevector_tests.cpp index 2c36f12389ee..01308cbbb312 100644 --- a/src/test/prevector_tests.cpp +++ b/src/test/prevector_tests.cpp @@ -53,13 +53,13 @@ class prevector_tester { local_check(pretype(real_vector.begin(), real_vector.end()) == pre_vector); local_check(pretype(pre_vector.begin(), pre_vector.end()) == pre_vector); size_t pos = 0; - BOOST_FOREACH(const T& v, pre_vector) { + for (const T& v : pre_vector) { local_check(v == real_vector[pos++]); } BOOST_REVERSE_FOREACH(const T& v, pre_vector) { local_check(v == real_vector[--pos]); } - BOOST_FOREACH(const T& v, const_pre_vector) { + for (const T& v : const_pre_vector) { local_check(v == real_vector[pos++]); } BOOST_REVERSE_FOREACH(const T& v, const_pre_vector) { diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index 13a996499be1..623dbf0efa20 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -676,7 +676,7 @@ BOOST_AUTO_TEST_CASE(script_build) std::string strGen; - BOOST_FOREACH(TestBuilder& test, tests) { + for (TestBuilder& test : tests) { test.Test(); std::string str = JSONPrettyPrint(test.GetJSON()); #ifndef UPDATE_JSON_TESTS @@ -769,7 +769,7 @@ sign_multisig(CScript scriptPubKey, std::vector keys, CTransaction transac // and vice-versa) // result << OP_0; - BOOST_FOREACH(const CKey &key, keys) + for (const CKey &key : keys) { std::vector vchSig; BOOST_CHECK(key.Sign(hash, vchSig)); diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index a99b6ac498fb..12fab1446669 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -159,7 +159,7 @@ CBlock TestChainSetup::CreateBlock(const std::vector& txns, block.vtx.resize(1); // Re-add quorum commitments block.vtx.insert(block.vtx.end(), llmqCommitments.begin(), llmqCommitments.end()); - BOOST_FOREACH(const CMutableTransaction& tx, txns) + for (const CMutableTransaction& tx : txns) block.vtx.push_back(MakeTransactionRef(tx)); // Manually update CbTx as we modified the block here diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 9681111828e1..dddeacf2d7b6 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -55,7 +55,7 @@ unsigned int ParseScriptFlags(std::string strFlags) std::vector words; boost::algorithm::split(words, strFlags, boost::algorithm::is_any_of(",")); - BOOST_FOREACH(std::string word, words) + for (std::string word : words) { if (!mapFlagNames.count(word)) BOOST_ERROR("Bad test: unknown verification flag '" << word << "'"); diff --git a/src/timedata.cpp b/src/timedata.cpp index e5cdd5497dd3..6549ecd53e12 100644 --- a/src/timedata.cpp +++ b/src/timedata.cpp @@ -95,7 +95,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) { // If nobody has a time different than ours but within 5 minutes of ours, give a warning bool fMatch = false; - BOOST_FOREACH(int64_t nOffset, vSorted) + for (int64_t nOffset : vSorted) if (nOffset != 0 && abs64(nOffset) < 5 * 60) fMatch = true; @@ -110,7 +110,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample) } if (LogAcceptCategory(BCLog::NET)) { - BOOST_FOREACH(int64_t n, vSorted) { + for (int64_t n : vSorted) { LogPrint(BCLog::NET, "%+d ", n); } LogPrint(BCLog::NET, "| "); diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index e2ba2209b1df..944b4e6f48d2 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -486,7 +486,7 @@ void TorController::add_onion_cb(TorControlConnection& _conn, const TorControlRe { if (reply.code == 250) { LogPrint(BCLog::TOR, "tor: ADD_ONION successful\n"); - BOOST_FOREACH(const std::string &s, reply.lines) { + for (const std::string &s : reply.lines) { std::map m = ParseTorReplyMapping(s); std::map::iterator i; if ((i = m.find("ServiceID")) != m.end()) @@ -616,7 +616,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro * 250-AUTH METHODS=NULL * 250-AUTH METHODS=HASHEDPASSWORD */ - BOOST_FOREACH(const std::string &s, reply.lines) { + for (const std::string &s : reply.lines) { std::pair l = SplitTorReplyLine(s); if (l.first == "AUTH") { std::map m = ParseTorReplyMapping(l.second); @@ -633,7 +633,7 @@ void TorController::protocolinfo_cb(TorControlConnection& _conn, const TorContro } } } - BOOST_FOREACH(const std::string &s, methods) { + for (const std::string &s : methods) { LogPrint(BCLog::TOR, "tor: Supported authentication method: %s\n", s); } // Prefer NULL, otherwise SAFECOOKIE. If a password is provided, use HASHEDPASSWORD diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 2542091c51d2..e5c8c5664ac3 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -74,12 +74,12 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan setAllDescendants.insert(cit); stageEntries.erase(cit); const setEntries &setChildren = GetMemPoolChildren(cit); - BOOST_FOREACH(const txiter childEntry, setChildren) { + for (const txiter childEntry : setChildren) { cacheMap::iterator cacheIt = cachedDescendants.find(childEntry); if (cacheIt != cachedDescendants.end()) { // We've already calculated this one, just add the entries for this set // but don't traverse again. - BOOST_FOREACH(const txiter cacheEntry, cacheIt->second) { + for (const txiter cacheEntry : cacheIt->second) { setAllDescendants.insert(cacheEntry); } } else if (!setAllDescendants.count(childEntry)) { @@ -93,7 +93,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan int64_t modifySize = 0; CAmount modifyFee = 0; int64_t modifyCount = 0; - BOOST_FOREACH(txiter cit, setAllDescendants) { + for (txiter cit : setAllDescendants) { if (!setExclude.count(cit->GetTx().GetHash())) { modifySize += cit->GetTxSize(); modifyFee += cit->GetModifiedFee(); @@ -203,7 +203,7 @@ bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntr } const setEntries & setMemPoolParents = GetMemPoolParents(stageit); - BOOST_FOREACH(const txiter &phash, setMemPoolParents) { + for (const txiter &phash : setMemPoolParents) { // If this is a new ancestor, add it. if (setAncestors.count(phash) == 0) { parentHashes.insert(phash); @@ -222,13 +222,13 @@ void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors { setEntries parentIters = GetMemPoolParents(it); // add or remove this tx as a child of each parent - BOOST_FOREACH(txiter piter, parentIters) { + for (txiter piter : parentIters) { UpdateChild(piter, it, add); } const int64_t updateCount = (add ? 1 : -1); const int64_t updateSize = updateCount * it->GetTxSize(); const CAmount updateFee = updateCount * it->GetModifiedFee(); - BOOST_FOREACH(txiter ancestorIt, setAncestors) { + for (txiter ancestorIt : setAncestors) { mapTx.modify(ancestorIt, update_descendant_state(updateSize, updateFee, updateCount)); } } @@ -239,7 +239,7 @@ void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncesto int64_t updateSize = 0; CAmount updateFee = 0; int updateSigOps = 0; - BOOST_FOREACH(txiter ancestorIt, setAncestors) { + for (txiter ancestorIt : setAncestors) { updateSize += ancestorIt->GetTxSize(); updateFee += ancestorIt->GetModifiedFee(); updateSigOps += ancestorIt->GetSigOpCount(); @@ -250,7 +250,7 @@ void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncesto void CTxMemPool::UpdateChildrenForRemoval(txiter it) { const setEntries &setMemPoolChildren = GetMemPoolChildren(it); - BOOST_FOREACH(txiter updateIt, setMemPoolChildren) { + for (txiter updateIt : setMemPoolChildren) { UpdateParent(updateIt, it, false); } } @@ -267,19 +267,19 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b // Here we only update statistics and not data in mapLinks (which // we need to preserve until we're finished with all operations that // need to traverse the mempool). - BOOST_FOREACH(txiter removeIt, entriesToRemove) { + for (txiter removeIt : entriesToRemove) { setEntries setDescendants; CalculateDescendants(removeIt, setDescendants); setDescendants.erase(removeIt); // don't update state for self int64_t modifySize = -((int64_t)removeIt->GetTxSize()); CAmount modifyFee = -removeIt->GetModifiedFee(); int modifySigOps = -removeIt->GetSigOpCount(); - BOOST_FOREACH(txiter dit, setDescendants) { + for (txiter dit : setDescendants) { mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps)); } } } - BOOST_FOREACH(txiter removeIt, entriesToRemove) { + for (txiter removeIt : entriesToRemove) { setEntries setAncestors; const CTxMemPoolEntry &entry = *removeIt; std::string dummy; @@ -308,7 +308,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b // After updating all the ancestor sizes, we can now sever the link between each // transaction being removed and any mempool children (ie, update setMemPoolParents // for each direct child of a transaction being removed). - BOOST_FOREACH(txiter removeIt, entriesToRemove) { + for (txiter removeIt : entriesToRemove) { UpdateChildrenForRemoval(removeIt); } } @@ -402,7 +402,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, // to clean up the mess we're leaving here. // Update ancestors with information about this tx - BOOST_FOREACH (const uint256 &phash, setParentTransactions) { + for (const uint256 &phash : setParentTransactions) { txiter pit = mapTx.find(phash); if (pit != mapTx.end()) { UpdateParent(newit, pit, true); @@ -628,7 +628,7 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) { NotifyEntryRemoved(it->GetSharedTx(), reason); const uint256 hash = it->GetTx().GetHash(); - BOOST_FOREACH(const CTxIn& txin, it->GetTx().vin) + for (const CTxIn& txin : it->GetTx().vin) mapNextTx.erase(txin.prevout); if (vTxHashes.size() > 1) { @@ -717,7 +717,7 @@ void CTxMemPool::CalculateDescendants(txiter entryit, setEntries &setDescendants stage.erase(it); const setEntries &setChildren = GetMemPoolChildren(it); - BOOST_FOREACH(const txiter &childiter, setChildren) { + for (const txiter &childiter : setChildren) { if (!setDescendants.count(childiter)) { stage.insert(childiter); } @@ -749,7 +749,7 @@ void CTxMemPool::removeRecursive(const CTransaction &origTx, MemPoolRemovalReaso } } setEntries setAllRemoves; - BOOST_FOREACH(txiter it, txToRemove) { + for (txiter it : txToRemove) { CalculateDescendants(it, setAllRemoves); } @@ -771,7 +771,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem // So it's critical that we remove the tx and not depend on the LockPoints. txToRemove.insert(it); } else if (it->GetSpendsCoinbase()) { - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (const CTxIn& txin : tx.vin) { indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash); if (it2 != mapTx.end()) continue; @@ -798,7 +798,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx) { // Remove transactions which depend on inputs of tx, recursively LOCK(cs); - BOOST_FOREACH(const CTxIn &txin, tx.vin) { + for (const CTxIn &txin : tx.vin) { auto it = mapNextTx.find(txin.prevout); if (it != mapNextTx.end()) { const CTransaction &txConflict = *it->second; @@ -1035,7 +1035,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const setEntries setParentCheck; int64_t parentSizes = 0; unsigned int parentSigOpCount = 0; - BOOST_FOREACH(const CTxIn &txin, tx.vin) { + for (const CTxIn &txin : tx.vin) { // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's. indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash); if (it2 != mapTx.end()) { @@ -1067,7 +1067,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const CAmount nFeesCheck = it->GetModifiedFee(); unsigned int nSigOpCheck = it->GetSigOpCount(); - BOOST_FOREACH(txiter ancestorIt, setAncestors) { + for (txiter ancestorIt : setAncestors) { nSizeCheck += ancestorIt->GetTxSize(); nFeesCheck += ancestorIt->GetModifiedFee(); nSigOpCheck += ancestorIt->GetSigOpCount(); @@ -1329,14 +1329,14 @@ void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeD uint64_t nNoLimit = std::numeric_limits::max(); std::string dummy; CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false); - BOOST_FOREACH(txiter ancestorIt, setAncestors) { + for (txiter ancestorIt : setAncestors) { mapTx.modify(ancestorIt, update_descendant_state(0, nFeeDelta, 0)); } // Now update all descendants' modified fees with ancestors setEntries setDescendants; CalculateDescendants(it, setDescendants); setDescendants.erase(it); - BOOST_FOREACH(txiter descendantIt, setDescendants) { + for (txiter descendantIt : setDescendants) { mapTx.modify(descendantIt, update_ancestor_state(0, nFeeDelta, 0, 0)); } ++nTransactionsUpdated; @@ -1396,7 +1396,7 @@ size_t CTxMemPool::DynamicMemoryUsage() const { void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason) { AssertLockHeld(cs); UpdateForRemoveFromMempool(stage, updateDescendants); - BOOST_FOREACH(const txiter& it, stage) { + for (const txiter& it : stage) { removeUnchecked(it, reason); } } @@ -1415,7 +1415,7 @@ int CTxMemPool::Expire(int64_t time) { it++; } setEntries stage; - BOOST_FOREACH(txiter removeit, toremove) { + for (txiter removeit : toremove) { CalculateDescendants(removeit, stage); } RemoveStaged(stage, false, MemPoolRemovalReason::EXPIRY); @@ -1524,13 +1524,13 @@ void CTxMemPool::TrimToSize(size_t sizelimit, std::vector* pvNoSpends std::vector txn; if (pvNoSpendsRemaining) { txn.reserve(stage.size()); - BOOST_FOREACH(txiter iter, stage) + for (txiter iter : stage) txn.push_back(iter->GetTx()); } RemoveStaged(stage, false, MemPoolRemovalReason::SIZELIMIT); if (pvNoSpendsRemaining) { - BOOST_FOREACH(const CTransaction& tx, txn) { - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (const CTransaction& tx : txn) { + for (const CTxIn& txin : tx.vin) { if (exists(txin.prevout.hash)) continue; pvNoSpendsRemaining->push_back(txin.prevout); } diff --git a/src/validation.cpp b/src/validation.cpp index 969d242119b6..2509da14dd9d 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -177,7 +177,7 @@ namespace { CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) { // Find the first block the caller has in the main chain - BOOST_FOREACH(const uint256& hash, locator.vHave) { + for (const uint256& hash : locator.vHave) { BlockMap::iterator mi = mapBlockIndex.find(hash); if (mi != mapBlockIndex.end()) { @@ -411,7 +411,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool // lock on a mempool input, so we can use the return value of // CheckSequenceLocks to indicate the LockPoints validity int maxInputHeight = 0; - BOOST_FOREACH(int height, prevheights) { + for (int height : prevheights) { // Can ignore mempool inputs since we'll fail if they had non-zero locks if (height != tip->nHeight+1) { maxInputHeight = std::max(maxInputHeight, height); @@ -579,7 +579,7 @@ static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) std::vector vNoSpendsRemaining; pool.TrimToSize(limit, &vNoSpendsRemaining); - BOOST_FOREACH(const COutPoint& removed, vNoSpendsRemaining) + for (const COutPoint& removed : vNoSpendsRemaining) pcoinsTip->Uncache(removed); } @@ -709,7 +709,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // Check for conflicts with in-memory transactions { LOCK(pool.cs); // protect pool.mapNextTx - BOOST_FOREACH(const CTxIn &txin, tx.vin) + for (const CTxIn &txin : tx.vin) { auto itConflicting = pool.mapNextTx.find(txin.prevout); if (itConflicting != pool.mapNextTx.end()) @@ -746,7 +746,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool } // do all inputs exist? - BOOST_FOREACH(const CTxIn txin, tx.vin) { + for (const CTxIn txin : tx.vin) { if (!pcoinsTip->HaveCoinInCache(txin.prevout)) { coins_to_uncache.push_back(txin.prevout); } @@ -791,7 +791,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // Keep track of transactions that spend a coinbase, which we re-scan // during reorgs to ensure COINBASE_MATURITY is still met. bool fSpendsCoinbase = false; - BOOST_FOREACH(const CTxIn &txin, tx.vin) { + for (const CTxIn &txin : tx.vin) { const Coin &coin = view.AccessCoin(txin.prevout); if (coin.IsCoinBase()) { fSpendsCoinbase = true; @@ -913,7 +913,7 @@ static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPo bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, fLimitFree, pfMissingInputs, nAcceptTime, fOverrideMempoolLimit, nAbsurdFee, coins_to_uncache, fDryRun); if (!res || fDryRun) { if(!res) LogPrint(BCLog::MEMPOOL, "%s: %s %s (%s)\n", __func__, tx->GetHash().ToString(), state.GetRejectReason(), state.GetDebugMessage()); - BOOST_FOREACH(const COutPoint& hashTx, coins_to_uncache) + for (const COutPoint& hashTx : coins_to_uncache) pcoinsTip->Uncache(hashTx); } // After we've (potentially) uncached entries, ensure our coins cache is still within its size limits @@ -1355,7 +1355,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txund // mark inputs spent if (!tx.IsCoinBase()) { txundo.vprevout.reserve(tx.vin.size()); - BOOST_FOREACH(const CTxIn &txin, tx.vin) { + for (const CTxIn &txin : tx.vin) { txundo.vprevout.emplace_back(); bool is_spent = inputs.SpendCoin(txin.prevout, &txundo.vprevout.back()); assert(is_spent); @@ -3710,7 +3710,7 @@ bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, static uint64_t CalculateCurrentUsage() { uint64_t retval = 0; - BOOST_FOREACH(const CBlockFileInfo &file, vinfoBlockFile) { + for (const CBlockFileInfo &file : vinfoBlockFile) { retval += file.nSize + file.nUndoSize; } return retval; @@ -3929,7 +3929,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) // Calculate nChainWork std::vector > vSortedByHeight; vSortedByHeight.reserve(mapBlockIndex.size()); - BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + for (const PAIRTYPE(uint256, CBlockIndex*)& item : mapBlockIndex) { CBlockIndex* pindex = item.second; vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex)); @@ -3940,7 +3940,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) } } sort(vSortedByHeight.begin(), vSortedByHeight.end()); - BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) + for (const PAIRTYPE(int, CBlockIndex*)& item : vSortedByHeight) { CBlockIndex* pindex = item.second; pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex); @@ -3989,7 +3989,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) // Check presence of blk files LogPrintf("Checking all blk files are present...\n"); std::set setBlkDataFiles; - BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + for (const PAIRTYPE(uint256, CBlockIndex*)& item : mapBlockIndex) { CBlockIndex* pindex = item.second; if (pindex->nStatus & BLOCK_HAVE_DATA) { @@ -4176,7 +4176,7 @@ void UnloadBlockIndex() warningcache[b].clear(); } - BOOST_FOREACH(BlockMap::value_type& entry, mapBlockIndex) { + for (BlockMap::value_type& entry : mapBlockIndex) { delete entry.second; } mapBlockIndex.clear(); diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 3e50059e6dd3..1f54d7430444 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -348,7 +348,7 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) return false; fUseCrypto = true; - BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys) + for (KeyMap::value_type& mKey : mapKeys) { const CKey &key = mKey.second; CPubKey vchPubKey = key.GetPubKey(); diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 67f9f223f01d..24f805562dc1 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -204,7 +204,7 @@ bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*reco } DbTxn* ptxn = bitdb.TxnBegin(); - BOOST_FOREACH(CDBEnv::KeyValPair& row, salvagedData) + for (CDBEnv::KeyValPair& row : salvagedData) { if (recoverKVcallback) { diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 8b5ccb97cd1e..05af581dc032 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -48,7 +48,7 @@ int64_t static DecodeDumpTime(const std::string &str) { std::string static EncodeDumpString(const std::string &str) { std::stringstream ret; - BOOST_FOREACH(unsigned char c, str) { + for (unsigned char c : str) { if (c <= 32 || c >= 128 || c == '%') { ret << '%' << HexStr(&c, &c + 1); } else { @@ -1311,7 +1311,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) UniValue response(UniValue::VARR); - BOOST_FOREACH (const UniValue& data, requests.getValues()) { + for (const UniValue& data : requests.getValues()) { const int64_t timestamp = std::max(GetImportTimestamp(data, now), minimumTimestamp); const UniValue result = ProcessImport(pwallet, data, timestamp); response.push_back(result); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 39a8267c81e0..0e668d7268df 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -86,13 +86,13 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) uint256 hash = wtx.GetHash(); entry.push_back(Pair("txid", hash.GetHex())); UniValue conflicts(UniValue::VARR); - BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts()) + for (const uint256& conflict : wtx.GetConflicts()) conflicts.push_back(conflict.GetHex()); entry.push_back(Pair("walletconflicts", conflicts)); entry.push_back(Pair("time", wtx.GetTxTime())); entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived)); - BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, wtx.mapValue) + for (const PAIRTYPE(std::string, std::string)& item : wtx.mapValue) entry.push_back(Pair(item.first, item.second)); } @@ -503,7 +503,7 @@ UniValue listaddressgroupings(const JSONRPCRequest& request) std::map balances = pwallet->GetAddressBalances(); for (std::set grouping : pwallet->GetAddressGroupings()) { UniValue jsonGrouping(UniValue::VARR); - BOOST_FOREACH(CTxDestination address, grouping) + for (CTxDestination address : grouping) { UniValue addressInfo(UniValue::VARR); addressInfo.push_back(CBitcoinAddress(address).ToString()); @@ -673,7 +673,7 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request) if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx)) continue; - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for (const CTxOut& txout : wtx.tx->vout) if (txout.scriptPubKey == scriptPubKey) if ((wtx.GetDepthInMainChain() >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend())) nAmount += txout.nValue; @@ -730,7 +730,7 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request) if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx)) continue; - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for (const CTxOut& txout : wtx.tx->vout) { CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwallet, address) && setAddress.count(address)) { @@ -1004,7 +1004,7 @@ UniValue sendmany(const JSONRPCRequest& request) CAmount totalAmount = 0; std::vector keys = sendTo.getKeys(); - BOOST_FOREACH(const std::string& name_, keys) + for (const std::string& name_ : keys) { CBitcoinAddress address(name_); if (!address.IsValid()) @@ -1158,7 +1158,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA if ((nDepth < nMinDepth) && !(fAddLocked && wtx.IsLockedByInstantSend())) continue; - BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) + for (const CTxOut& txout : wtx.tx->vout) { CTxDestination address; if (!ExtractDestination(txout.scriptPubKey, address)) @@ -1222,7 +1222,7 @@ UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool fByA UniValue transactions(UniValue::VARR); if (it != mapTally.end()) { - BOOST_FOREACH(const uint256& _item, (*it).second.txids) + for (const uint256& _item : (*it).second.txids) { transactions.push_back(_item.GetHex()); } @@ -1360,7 +1360,7 @@ void ListTransactions(CWallet * const pwallet, const CWalletTx& wtx, const std:: // Sent if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount)) { - BOOST_FOREACH(const COutputEntry& s, listSent) + for (const COutputEntry& s : listSent) { UniValue entry(UniValue::VOBJ); if (involvesWatchonly || (::IsMine(*pwallet, s.destination) & ISMINE_WATCH_ONLY)) { @@ -1386,7 +1386,7 @@ void ListTransactions(CWallet * const pwallet, const CWalletTx& wtx, const std:: // Received if (listReceived.size() > 0 && ((wtx.GetDepthInMainChain() >= nMinDepth) || wtx.IsLockedByInstantSend())) { - BOOST_FOREACH(const COutputEntry& r, listReceived) + for (const COutputEntry& r : listReceived) { std::string account; if (pwallet->mapAddressBook.count(r.destination)) { @@ -1634,11 +1634,11 @@ UniValue listaccounts(const JSONRPCRequest& request) continue; wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly); mapAccountBalances[strSentAccount] -= nFee; - BOOST_FOREACH(const COutputEntry& s, listSent) + for (const COutputEntry& s : listSent) mapAccountBalances[strSentAccount] -= s.amount; if ((nDepth >= nMinDepth) || (fAddLocked && wtx.IsLockedByInstantSend())) { - BOOST_FOREACH(const COutputEntry& r, listReceived) + for (const COutputEntry& r : listReceived) if (pwallet->mapAddressBook.count(r.destination)) { mapAccountBalances[pwallet->mapAddressBook[r.destination].name] += r.amount; } @@ -1648,11 +1648,11 @@ UniValue listaccounts(const JSONRPCRequest& request) } const std::list & acentries = pwallet->laccentries; - BOOST_FOREACH(const CAccountingEntry& entry, acentries) + for (const CAccountingEntry& entry : acentries) mapAccountBalances[entry.strAccount] += entry.nCreditDebit; UniValue ret(UniValue::VOBJ); - BOOST_FOREACH(const PAIRTYPE(std::string, CAmount)& accountBalance, mapAccountBalances) { + for (const PAIRTYPE(std::string, CAmount)& accountBalance : mapAccountBalances) { ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second))); } return ret; @@ -2327,7 +2327,7 @@ UniValue listlockunspent(const JSONRPCRequest& request) UniValue ret(UniValue::VARR); - BOOST_FOREACH(COutPoint &outpt, vOutpts) { + for (COutPoint &outpt : vOutpts) { UniValue o(UniValue::VOBJ); o.push_back(Pair("txid", outpt.hash.GetHex())); @@ -2583,7 +2583,7 @@ UniValue resendwallettransactions(const JSONRPCRequest& request) std::vector txids = pwallet->ResendWalletTransactionsBefore(GetTime(), g_connman.get()); UniValue result(UniValue::VARR); - BOOST_FOREACH(const uint256& txid, txids) + for (const uint256& txid : txids) { result.push_back(txid.ToString()); } @@ -2709,7 +2709,7 @@ UniValue listunspent(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); pwallet->AvailableCoins(vecOutputs, !include_unsafe, NULL, nMinimumAmount, nMaximumAmount, nMinimumSumAmount, nMaximumCount, nMinDepth, nMaxDepth); - BOOST_FOREACH(const COutput& out, vecOutputs) { + for (const COutput& out : vecOutputs) { CTxDestination address; const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey; bool fValidAddress = ExtractDestination(scriptPubKey, address); diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp index eb14d176bd70..927aa980c198 100644 --- a/src/wallet/test/accounting_tests.cpp +++ b/src/wallet/test/accounting_tests.cpp @@ -23,7 +23,7 @@ GetResults(std::map& results) results.clear(); BOOST_CHECK(pwalletMain->ReorderTransactions() == DB_LOAD_OK); pwalletMain->ListAccountCreditDebit("", aes); - BOOST_FOREACH(CAccountingEntry& ae, aes) + for (CAccountingEntry& ae : aes) { results[ae.nOrderPos] = ae; } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 976d55f7b5c0..065dadf7afe8 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -436,7 +436,7 @@ bool CWallet::Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnl { LOCK(cs_wallet); - BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + for (const MasterKeyMap::value_type& pMasterKey : mapMasterKeys) { if (!crypter.SetKeyFromPassphrase(strWalletPassphraseFinal, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) return false; @@ -481,7 +481,7 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, CCrypter crypter; CKeyingMaterial _vMasterKey; - BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys) + for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys) { if(!crypter.SetKeyFromPassphrase(strOldWalletPassphraseFinal, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod)) return false; @@ -585,7 +585,7 @@ std::set CWallet::GetConflicts(const uint256& txid) const std::pair range; - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) { if (mapTxSpends.count(txin.prevout) <= 1) continue; // No conflict if zero or one spends @@ -711,7 +711,7 @@ void CWallet::AddToSpends(const uint256& wtxid) if (thisTx.IsCoinBase()) // Coinbases don't spend anything! return; - BOOST_FOREACH(const CTxIn& txin, thisTx.tx->vin) + for (const CTxIn& txin : thisTx.tx->vin) AddToSpends(txin.prevout, wtxid); } @@ -858,7 +858,7 @@ DBErrors CWallet::ReorderTransactions() } std::list acentries; walletdb.ListAccountCreditDebit("", acentries); - BOOST_FOREACH(CAccountingEntry& entry, acentries) + for (CAccountingEntry& entry : acentries) { txByTime.insert(std::make_pair(entry.nTime, TxPair((CWalletTx*)0, &entry))); } @@ -888,7 +888,7 @@ DBErrors CWallet::ReorderTransactions() else { int64_t nOrderPosOff = 0; - BOOST_FOREACH(const int64_t& nOffsetStart, nOrderPosOffsets) + for (const int64_t& nOffsetStart : nOrderPosOffsets) { if (nOrderPos >= nOffsetStart) ++nOrderPosOff; @@ -977,7 +977,7 @@ bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bFo for (std::map::iterator it = mapWallet.begin(); it != mapWallet.end() && account.vchPubKey.IsValid(); ++it) - BOOST_FOREACH(const CTxOut& txout, (*it).second.tx->vout) + for (const CTxOut& txout : (*it).second.tx->vout) if (txout.scriptPubKey == scriptPubKey) { bForceNew = true; break; @@ -1003,7 +1003,7 @@ void CWallet::MarkDirty() { { LOCK(cs_wallet); - BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + for (PAIRTYPE(const uint256, CWalletTx)& item : mapWallet) item.second.MarkDirty(); } @@ -1108,7 +1108,7 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn) wtx.BindWallet(this); wtxOrdered.insert(std::make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0))); AddToSpends(hash); - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) { + for (const CTxIn& txin : wtx.tx->vin) { if (mapWallet.count(txin.prevout.hash)) { CWalletTx& prevtx = mapWallet[txin.prevout.hash]; if (prevtx.nIndex == -1 && !prevtx.hashUnset()) { @@ -1140,7 +1140,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, const CBlockI AssertLockHeld(cs_wallet); if (pIndex != NULL) { - BOOST_FOREACH(const CTxIn& txin, tx.vin) { + for (const CTxIn& txin : tx.vin) { std::pair range = mapTxSpends.equal_range(txin.prevout); while (range.first != range.second) { if (range.first->second != tx.GetHash()) { @@ -1214,7 +1214,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) } // If a transaction changes 'conflicted' state, that changes the balance // available of the outputs it spends. So force those to be recomputed - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) { if (mapWallet.count(txin.prevout.hash)) mapWallet[txin.prevout.hash].MarkDirty(); @@ -1278,7 +1278,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) } // If a transaction changes 'conflicted' state, that changes the balance // available of the outputs it spends. So force those to be recomputed - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) { if (mapWallet.count(txin.prevout.hash)) mapWallet[txin.prevout.hash].MarkDirty(); @@ -1299,7 +1299,7 @@ void CWallet::SyncTransaction(const CTransactionRef& ptx, const CBlockIndex *pin // If a transaction changes 'conflicted' state, that changes the balance // available of the outputs it spends. So force those to be // recomputed, also: - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { if (mapWallet.count(txin.prevout.hash)) mapWallet[txin.prevout.hash].MarkDirty(); @@ -1649,7 +1649,7 @@ bool CWallet::IsHDEnabled() const bool CWallet::IsMine(const CTransaction& tx) const { - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const CTxOut& txout : tx.vout) if (IsMine(txout)) return true; return false; @@ -1663,7 +1663,7 @@ bool CWallet::IsFromMe(const CTransaction& tx) const CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const { CAmount nDebit = 0; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { nDebit += GetDebit(txin, filter); if (!MoneyRange(nDebit)) @@ -1676,7 +1676,7 @@ bool CWallet::IsAllFromMe(const CTransaction& tx, const isminefilter& filter) co { LOCK(cs_wallet); - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) { auto mi = mapWallet.find(txin.prevout.hash); if (mi == mapWallet.end()) @@ -1696,7 +1696,7 @@ bool CWallet::IsAllFromMe(const CTransaction& tx, const isminefilter& filter) co CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) const { CAmount nCredit = 0; - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const CTxOut& txout : tx.vout) { nCredit += GetCredit(txout, filter); if (!MoneyRange(nCredit)) @@ -1708,7 +1708,7 @@ CAmount CWallet::GetCredit(const CTransaction& tx, const isminefilter& filter) c CAmount CWallet::GetChange(const CTransaction& tx) const { CAmount nChange = 0; - BOOST_FOREACH(const CTxOut& txout, tx.vout) + for (const CTxOut& txout : tx.vout) { nChange += GetChange(txout); if (!MoneyRange(nChange)) @@ -1885,7 +1885,7 @@ void CWallet::ReacceptWalletTransactions() std::map mapSorted; // Sort pending wallet transactions based on their initial wallet insertion order - BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + for (PAIRTYPE(const uint256, CWalletTx)& item : mapWallet) { const uint256& wtxid = item.first; CWalletTx& wtx = item.second; @@ -1899,7 +1899,7 @@ void CWallet::ReacceptWalletTransactions() } // Try to add wallet transactions to memory pool - BOOST_FOREACH(PAIRTYPE(const int64_t, CWalletTx*)& item, mapSorted) + for (PAIRTYPE(const int64_t, CWalletTx*)& item : mapSorted) { CWalletTx& wtx = *(item.second); @@ -2206,7 +2206,7 @@ bool CWalletTx::IsTrusted() const return false; // Trusted if all inputs are from us and are in the mempool: - BOOST_FOREACH(const CTxIn& txin, tx->vin) + for (const CTxIn& txin : tx->vin) { // Transactions not sent by us: not trusted const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash); @@ -2235,7 +2235,7 @@ std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime, CCon LOCK(cs_wallet); // Sort them in chronological order std::multimap mapSorted; - BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + for (PAIRTYPE(const uint256, CWalletTx)& item : mapWallet) { CWalletTx& wtx = item.second; // Don't rebroadcast if newer than nTime: @@ -2243,7 +2243,7 @@ std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime, CCon continue; mapSorted.insert(std::make_pair(wtx.nTimeReceived, &wtx)); } - BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted) + for (PAIRTYPE(const unsigned int, CWalletTx*)& item : mapSorted) { CWalletTx& wtx = *item.second; if (wtx.RelayWalletTransaction(connman)) @@ -2729,7 +2729,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, const int nConfMin LogPrint(BCLog::SELECTCOINS, "tryDenom: %d\n", tryDenom); vValue.clear(); nTotalLower = 0; - BOOST_FOREACH(const COutput &output, vCoins) + for (const COutput &output : vCoins) { if (!output.fSpendable) continue; @@ -2851,7 +2851,7 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) if (coinControl && coinControl->HasSelected() && !coinControl->fAllowOtherInputs) { - BOOST_FOREACH(const COutput& out, vCoins) + for (const COutput& out : vCoins) { if(!out.fSpendable) continue; @@ -2881,7 +2881,7 @@ bool CWallet::SelectCoins(const std::vector& vAvailableCoins, const CAm std::vector vPresetInputs; if (coinControl) coinControl->ListSelected(vPresetInputs); - BOOST_FOREACH(const COutPoint& outpoint, vPresetInputs) + for (const COutPoint& outpoint : vPresetInputs) { std::map::const_iterator it = mapWallet.find(outpoint.hash); if (it != mapWallet.end()) @@ -2951,7 +2951,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov coinControl.fOverrideFeeRate = overrideEstimatedFeeRate; coinControl.nFeeRate = specificFeeRate; - BOOST_FOREACH(const CTxIn& txin, tx.vin) + for (const CTxIn& txin : tx.vin) coinControl.Select(txin.prevout); int nExtraPayloadSize = 0; @@ -2971,7 +2971,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov tx.vout[idx].nValue = wtx.tx->vout[idx].nValue; // Add new txins (keeping original txin scriptSig/order) - BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) + for (const CTxIn& txin : wtx.tx->vin) { if (!coinControl.IsSelected(txin.prevout)) { @@ -3614,7 +3614,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // If there was change output added before, we must update its position now if (nChangePosInOut != -1) { int i = 0; - BOOST_FOREACH(const CTxOut& txOut, txNew.vout) + for (const CTxOut& txOut : txNew.vout) { if (txOut == newTxOut) { @@ -3773,7 +3773,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon // Notify that old coins are spent std::set updated_hahes; - BOOST_FOREACH(const CTxIn& txin, wtxNew.tx->vin) + for (const CTxIn& txin : wtxNew.tx->vin) { // notify only once if(updated_hahes.find(txin.prevout.hash) != updated_hahes.end()) continue; @@ -3987,7 +3987,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address) // Delete destdata tuples associated with address std::string strAddress = CBitcoinAddress(address).ToString(); - BOOST_FOREACH(const PAIRTYPE(std::string, std::string) &item, mapAddressBook[address].destdata) + for (const PAIRTYPE(std::string, std::string) &item : mapAddressBook[address].destdata) { CWalletDB(*dbw).EraseDestData(strAddress, item.first); } @@ -4032,11 +4032,11 @@ bool CWallet::NewKeyPool() { LOCK(cs_wallet); CWalletDB walletdb(*dbw); - BOOST_FOREACH(int64_t nIndex, setInternalKeyPool) { + for (int64_t nIndex : setInternalKeyPool) { walletdb.ErasePool(nIndex); } setInternalKeyPool.clear(); - BOOST_FOREACH(int64_t nIndex, setExternalKeyPool) { + for (int64_t nIndex : setExternalKeyPool) { walletdb.ErasePool(nIndex); } setExternalKeyPool.clear(); @@ -4291,7 +4291,7 @@ std::set< std::set > CWallet::GetAddressGroupings() { bool any_mine = false; // group all input addresses with each other - BOOST_FOREACH(CTxIn txin, pcoin->tx->vin) + for (CTxIn txin : pcoin->tx->vin) { CTxDestination address; if(!IsMine(txin)) /* If this input isn't mine, ignore it */ @@ -4305,7 +4305,7 @@ std::set< std::set > CWallet::GetAddressGroupings() // group change with input addresses if (any_mine) { - BOOST_FOREACH(CTxOut txout, pcoin->tx->vout) + for (CTxOut txout : pcoin->tx->vout) if (IsChange(txout)) { CTxDestination txoutAddr; @@ -4336,18 +4336,18 @@ std::set< std::set > CWallet::GetAddressGroupings() std::set< std::set* > uniqueGroupings; // a set of pointers to groups of addresses std::map< CTxDestination, std::set* > setmap; // map addresses to the unique group containing it - BOOST_FOREACH(std::set _grouping, groupings) + for (std::set _grouping : groupings) { // make a set of all the groups hit by this new group std::set< std::set* > hits; std::map< CTxDestination, std::set* >::iterator it; - BOOST_FOREACH(CTxDestination address, _grouping) + for (CTxDestination address : _grouping) if ((it = setmap.find(address)) != setmap.end()) hits.insert((*it).second); // merge all hit groups into a new single group and delete old groups std::set* merged = new std::set(_grouping); - BOOST_FOREACH(std::set* hit, hits) + for (std::set* hit : hits) { merged->insert(hit->begin(), hit->end()); uniqueGroupings.erase(hit); @@ -4356,12 +4356,12 @@ std::set< std::set > CWallet::GetAddressGroupings() uniqueGroupings.insert(merged); // update setmap - BOOST_FOREACH(CTxDestination element, *merged) + for (CTxDestination element : *merged) setmap[element] = merged; } std::set< std::set > ret; - BOOST_FOREACH(std::set* uniqueGrouping, uniqueGroupings) + for (std::set* uniqueGrouping : uniqueGroupings) { ret.insert(*uniqueGrouping); delete uniqueGrouping; @@ -4374,7 +4374,7 @@ std::set CWallet::GetAccountAddresses(const std::string& strAcco { LOCK(cs_wallet); std::set result; - BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook) + for (const PAIRTYPE(CTxDestination, CAddressBookData)& item : mapAddressBook) { const CTxDestination& address = item.first; const std::string& strName = item.second.name; @@ -4423,7 +4423,7 @@ void CReserveKey::ReturnKey() static void LoadReserveKeysToSet(std::set& setAddress, const std::set& setKeyPool, CWalletDB& walletdb) { - BOOST_FOREACH(const int64_t& id, setKeyPool) + for (const int64_t& id : setKeyPool) { CKeyPool keypool; if (!walletdb.ReadPool(id, keypool)) @@ -4444,7 +4444,7 @@ void CWallet::GetAllReserveKeys(std::set& setAddress) const LoadReserveKeysToSet(setAddress, setInternalKeyPool, walletdb); LoadReserveKeysToSet(setAddress, setExternalKeyPool, walletdb); - BOOST_FOREACH (const CKeyID& keyID, setAddress) { + for (const CKeyID& keyID : setAddress) { if (!HaveKey(keyID)) { throw std::runtime_error(std::string(__func__) + ": unknown key in key pool"); } @@ -4538,7 +4538,7 @@ class CAffectedKeysVisitor : public boost::static_visitor { std::vector vDest; int nRequired; if (ExtractDestinations(script, type, vDest, nRequired)) { - BOOST_FOREACH(const CTxDestination &dest, vDest) + for (const CTxDestination &dest : vDest) boost::apply_visitor(*this, dest); } } @@ -4573,7 +4573,7 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) c std::map mapKeyFirstBlock; std::set setKeys; GetKeys(setKeys); - BOOST_FOREACH(const CKeyID &keyid, setKeys) { + for (const CKeyID &keyid : setKeys) { if (mapKeyBirth.count(keyid) == 0) mapKeyFirstBlock[keyid] = pindexMax; } @@ -4592,10 +4592,10 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) c if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) { // ... which are already in a block int nHeight = blit->second->nHeight; - BOOST_FOREACH(const CTxOut &txout, wtx.tx->vout) { + for (const CTxOut &txout : wtx.tx->vout) { // iterate over all their outputs CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey); - BOOST_FOREACH(const CKeyID &keyid, vAffected) { + for (const CKeyID &keyid : vAffected) { // ... and all their affected keys std::map::iterator rit = mapKeyFirstBlock.find(keyid); if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) @@ -4934,7 +4934,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) { CWalletDB walletdb(*walletInstance->dbw); - BOOST_FOREACH(const CWalletTx& wtxOld, vWtx) + for (const CWalletTx& wtxOld : vWtx) { uint256 hash = wtxOld.GetHash(); std::map::iterator mi = walletInstance->mapWallet.find(hash); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index ec6871036470..a2d0a2fc080b 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -208,7 +208,7 @@ CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount) ListAccountCreditDebit(strAccount, entries); CAmount nCreditDebit = 0; - BOOST_FOREACH (const CAccountingEntry& entry, entries) + for (const CAccountingEntry& entry : entries) nCreditDebit += entry.nCreditDebit; return nCreditDebit; @@ -668,7 +668,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta) pwallet->UpdateTimeFirstKey(1); - BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade) + for (uint256 hash : wss.vWalletUpgrade) WriteTx(pwallet->mapWallet[hash]); // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: @@ -683,7 +683,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) pwallet->laccentries.clear(); ListAccountCreditDebit("*", pwallet->laccentries); - BOOST_FOREACH(CAccountingEntry& entry, pwallet->laccentries) { + for (CAccountingEntry& entry : pwallet->laccentries) { pwallet->wtxOrdered.insert(make_pair(entry.nOrderPos, CWallet::TxPair((CWalletTx*)0, &entry))); } @@ -769,7 +769,7 @@ DBErrors CWalletDB::ZapSelectTx(std::vector& vTxHashIn, std::vector::iterator it = vTxHashIn.begin(); - BOOST_FOREACH (uint256 hash, vTxHash) { + for (uint256 hash : vTxHash) { while (it < vTxHashIn.end() && (*it) < hash) { it++; } @@ -800,7 +800,7 @@ DBErrors CWalletDB::ZapWalletTx(std::vector& vWtx) return err; // erase each wallet TX - BOOST_FOREACH (uint256& hash, vTxHash) { + for (uint256& hash : vTxHash) { if (!EraseTx(hash)) return DB_CORRUPT; } From 0d52db844c59e8481fb5871d40d42b83c1814e5e Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 5 Jul 2019 02:07:45 -0500 Subject: [PATCH 376/987] scripted-diff: Remove Q_FOREACH #10502 -BEGIN VERIFY SCRIPT- sed -i 's/Q_FOREACH *(\(.*\),/for (\1 :/' ./src/*.h ./src/*.cpp ./src/*/*.h ./src/*/*.cpp ./src/*/*/*.h ./src/*/*/*.cpp ; -END VERIFY SCRIPT- --- src/qt/addressbookpage.cpp | 2 +- src/qt/bitcoingui.cpp | 6 +++--- src/qt/coincontroldialog.cpp | 2 +- src/qt/optionsdialog.cpp | 2 +- src/qt/paymentserver.cpp | 10 +++++----- src/qt/peertablemodel.cpp | 4 ++-- src/qt/platformstyle.cpp | 2 +- src/qt/receivecoinsdialog.cpp | 2 +- src/qt/sendcoinsdialog.cpp | 4 ++-- src/qt/splashscreen.cpp | 2 +- src/qt/test/paymentservertests.cpp | 2 +- src/qt/trafficgraphwidget.cpp | 2 +- src/qt/transactiondesc.cpp | 4 ++-- src/qt/transactiontablemodel.cpp | 2 +- src/qt/transactionview.cpp | 2 +- src/qt/utilitydialog.cpp | 2 +- src/qt/walletmodel.cpp | 6 +++--- src/qt/walletmodeltransaction.cpp | 2 +- 18 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index a30c06ecae0e..4adceae6246e 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -280,7 +280,7 @@ void AddressBookPage::done(int retval) // Figure out which address was selected, and return it QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); - Q_FOREACH (const QModelIndex& index, indexes) { + for (const QModelIndex& index : indexes) { QVariant address = table->model()->data(index); returnValue = address.toString(); } diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 2c0ab0e950a6..cc90e89d6415 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -1254,7 +1254,7 @@ void BitcoinGUI::dropEvent(QDropEvent *event) { if(event->mimeData()->hasUrls()) { - Q_FOREACH(const QUrl &uri, event->mimeData()->urls()) + for (const QUrl &uri : event->mimeData()->urls()) { Q_EMIT receivedURI(uri.toString()); } @@ -1476,7 +1476,7 @@ UnitDisplayStatusBarControl::UnitDisplayStatusBarControl(const PlatformStyle *pl QList units = BitcoinUnits::availableUnits(); int max_width = 0; const QFontMetrics fm(font()); - Q_FOREACH (const BitcoinUnits::Unit unit, units) + for (const BitcoinUnits::Unit unit : units) { max_width = qMax(max_width, fm.width(BitcoinUnits::name(unit))); } @@ -1495,7 +1495,7 @@ void UnitDisplayStatusBarControl::mousePressEvent(QMouseEvent *event) void UnitDisplayStatusBarControl::createContextMenu() { menu = new QMenu(this); - Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) + for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits()) { QAction *menuAction = new QAction(QString(BitcoinUnits::name(u)), this); menuAction->setData(QVariant(u)); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index e96c313c90a5..9b045277c0fd 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -478,7 +478,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) CAmount nPayAmount = 0; bool fDust = false; CMutableTransaction txDummy; - Q_FOREACH(const CAmount &amount, CoinControlDialog::payAmounts) + for (const CAmount &amount : CoinControlDialog::payAmounts) { nPayAmount += amount; diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index da3789742064..83cbe5186d30 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -106,7 +106,7 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : ui->lang->setToolTip(ui->lang->toolTip().arg(tr(PACKAGE_NAME))); ui->lang->addItem(QString("(") + tr("default") + QString(")"), QVariant("")); - Q_FOREACH(const QString &langStr, translations.entryList()) + for (const QString &langStr : translations.entryList()) { QLocale locale(langStr); diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 22eff5dcfe5f..03d6f1d42375 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -145,7 +145,7 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store) int nRootCerts = 0; const QDateTime currentTime = QDateTime::currentDateTime(); - Q_FOREACH (const QSslCertificate& cert, certList) { + for (const QSslCertificate& cert : certList) { // Don't log NULL certificates if (cert.isNull()) continue; @@ -268,7 +268,7 @@ void PaymentServer::ipcParseCommandLine(int argc, char* argv[]) bool PaymentServer::ipcSendCommandLine() { bool fResult = false; - Q_FOREACH (const QString& r, savedPaymentRequests) + for (const QString& r : savedPaymentRequests) { QLocalSocket* socket = new QLocalSocket(); socket->connectToServer(ipcServerName(), QIODevice::WriteOnly); @@ -393,7 +393,7 @@ void PaymentServer::uiReady() initNetManager(); saveURIs = false; - Q_FOREACH (const QString& s, savedPaymentRequests) + for (const QString& s : savedPaymentRequests) { handleURIOrFile(s); } @@ -556,7 +556,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen QList > sendingTos = request.getPayTo(); QStringList addresses; - Q_FOREACH(const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { + for (const PAIRTYPE(CScript, CAmount)& sendingTo : sendingTos) { // Extract and check destination addresses CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) { @@ -743,7 +743,7 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList Q_UNUSED(reply); QString errString; - Q_FOREACH (const QSslError& err, errs) { + for (const QSslError& err : errs) { qWarning() << "PaymentServer::reportSslErrors: " << err; errString += err.errorString() + "\n"; } diff --git a/src/qt/peertablemodel.cpp b/src/qt/peertablemodel.cpp index 6f4eb86a3632..b81b644da98d 100644 --- a/src/qt/peertablemodel.cpp +++ b/src/qt/peertablemodel.cpp @@ -62,7 +62,7 @@ class PeerTablePriv #if QT_VERSION >= 0x040700 cachedNodeStats.reserve(vstats.size()); #endif - Q_FOREACH (const CNodeStats& nodestats, vstats) + for (const CNodeStats& nodestats : vstats) { CNodeCombinedStats stats; stats.nodeStateStats.nMisbehavior = 0; @@ -91,7 +91,7 @@ class PeerTablePriv // build index map mapNodeRows.clear(); int row = 0; - Q_FOREACH (const CNodeCombinedStats& stats, cachedNodeStats) + for (const CNodeCombinedStats& stats : cachedNodeStats) mapNodeRows.insert(std::pair(stats.nodeStats.nodeid, row++)); } diff --git a/src/qt/platformstyle.cpp b/src/qt/platformstyle.cpp index 436c294f3c90..4d66e8d5f247 100644 --- a/src/qt/platformstyle.cpp +++ b/src/qt/platformstyle.cpp @@ -48,7 +48,7 @@ void MakeSingleColorImage(QImage& img, const QColor& colorbase) QIcon ColorizeIcon(const QIcon& ico, const QColor& colorbase) { QIcon new_ico; - Q_FOREACH(const QSize sz, ico.availableSizes()) + for (const QSize sz : ico.availableSizes()) { QImage img(ico.pixmap(sz).toImage()); MakeSingleColorImage(img, colorbase); diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 11a105cb5661..d9b566e3ebb9 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -192,7 +192,7 @@ void ReceiveCoinsDialog::on_showRequestButton_clicked() return; QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows(); - Q_FOREACH (const QModelIndex& index, selection) { + for (const QModelIndex& index : selection) { on_recentRequestsView_doubleClicked(index); } } diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index bc9e57137024..729d7b49e5f8 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -329,7 +329,7 @@ void SendCoinsDialog::send(QList recipients, QString strFee, // Format confirmation message QStringList formatted; - Q_FOREACH(const SendCoinsRecipient &rcp, currentTransaction.getRecipients()) + for (const SendCoinsRecipient &rcp : currentTransaction.getRecipients()) { // generate bold amount string QString amount = "" + BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount); @@ -386,7 +386,7 @@ void SendCoinsDialog::send(QList recipients, QString strFee, questionString.append("
    "); CAmount totalAmount = currentTransaction.getTotalTransactionAmount() + txFee; QStringList alternativeUnits; - Q_FOREACH(BitcoinUnits::Unit u, BitcoinUnits::availableUnits()) + for (BitcoinUnits::Unit u : BitcoinUnits::availableUnits()) { if(u != model->getOptionsModel()->getDisplayUnit()) alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount)); diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp index d90f32483aea..1d37fa49a7ce 100644 --- a/src/qt/splashscreen.cpp +++ b/src/qt/splashscreen.cpp @@ -192,7 +192,7 @@ void SplashScreen::unsubscribeFromCoreSignals() uiInterface.InitMessage.disconnect(boost::bind(InitMessage, this, _1)); uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); #ifdef ENABLE_WALLET - Q_FOREACH(CWallet* const & pwallet, connectedWallets) { + for (CWallet* const & pwallet : connectedWallets) { pwallet->ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2)); } #endif diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index 08a76c7d4963..e812c5c38883 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -196,7 +196,7 @@ void PaymentServerTests::paymentServerTests() QVERIFY(r.paymentRequest.IsInitialized()); // Extract address and amount from the request QList > sendingTos = r.paymentRequest.getPayTo(); - Q_FOREACH (const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) { + for (const PAIRTYPE(CScript, CAmount)& sendingTo : sendingTos) { CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false); diff --git a/src/qt/trafficgraphwidget.cpp b/src/qt/trafficgraphwidget.cpp index 8266f553c6dd..05029bc1f2d1 100644 --- a/src/qt/trafficgraphwidget.cpp +++ b/src/qt/trafficgraphwidget.cpp @@ -155,7 +155,7 @@ void TrafficGraphWidget::updateRates() if (updated){ float tmax = DEFAULT_SAMPLE_HEIGHT; - Q_FOREACH(const TrafficSample& sample, trafficGraphData.getCurrentRangeQueueWithAverageBandwidth()) { + for (const TrafficSample& sample : trafficGraphData.getCurrentRangeQueueWithAverageBandwidth()) { if(sample.in > tmax) tmax = sample.in; if(sample.out > tmax) tmax = sample.out; } diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 3a1f395dd769..5f5b6bd25dea 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -261,14 +261,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "" + tr("Transaction total size") + ": " + QString::number(wtx.tx->GetTotalSize()) + " bytes
    "; // Message from normal dash:URI (dash:XyZ...?message=example) - Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm) + for (const PAIRTYPE(std::string, std::string)& r : wtx.vOrderForm) if (r.first == "Message") strHTML += "
    " + tr("Message") + ":
    " + GUIUtil::HtmlEscape(r.second, true) + "
    "; // // PaymentRequest info: // - Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm) + for (const PAIRTYPE(std::string, std::string)& r : wtx.vOrderForm) { if (r.first == "PaymentRequest") { diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 96fa10bdfb65..954b92860be2 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -144,7 +144,7 @@ class TransactionTablePriv { parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1); int insert_idx = lowerIndex; - Q_FOREACH(const TransactionRecord &rec, toInsert) + for (const TransactionRecord &rec : toInsert) { cachedWallet.insert(insert_idx, rec); insert_idx += 1; diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 7f2be564b502..84e796b97dc4 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -574,7 +574,7 @@ void TransactionView::computeSum() return; QModelIndexList selection = transactionView->selectionModel()->selectedRows(); - Q_FOREACH (QModelIndex index, selection){ + for (QModelIndex index : selection){ amount += index.data(TransactionTableModel::AmountRole).toLongLong(); } QString strAmount(BitcoinUnits::formatWithUnit(nDisplayUnit, amount, true, BitcoinUnits::separatorAlways)); diff --git a/src/qt/utilitydialog.cpp b/src/qt/utilitydialog.cpp index e5e729df54a5..d8fc1c943c36 100644 --- a/src/qt/utilitydialog.cpp +++ b/src/qt/utilitydialog.cpp @@ -108,7 +108,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, HelpMode helpMode) : QTextCharFormat bold; bold.setFontWeight(QFont::Bold); - Q_FOREACH (const QString &line, coreOptions.split("\n")) { + for (const QString &line : coreOptions.split("\n")) { if (line.startsWith(" -")) { cursor.currentTable()->appendRows(1); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index b621202459b1..748f65ee5c71 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -256,7 +256,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact int nAddresses = 0; // Pre-check input data for validity - Q_FOREACH(const SendCoinsRecipient &rcp, recipients) + for (const SendCoinsRecipient &rcp : recipients) { if (rcp.fSubtractFeeFromAmount) fSubtractFeeFromAmount = true; @@ -367,7 +367,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran CWalletTx *newTx = transaction.getTransaction(); QList recipients = transaction.getRecipients(); - Q_FOREACH(const SendCoinsRecipient &rcp, recipients) + for (const SendCoinsRecipient &rcp : recipients) { if (rcp.paymentRequest.IsInitialized()) { @@ -400,7 +400,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran // Add addresses / update labels that we've sent to to the address book, // and emit coinsSent signal for each recipient - Q_FOREACH(const SendCoinsRecipient &rcp, transaction.getRecipients()) + for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { // Don't touch the address book when we have a payment request if (!rcp.paymentRequest.IsInitialized()) diff --git a/src/qt/walletmodeltransaction.cpp b/src/qt/walletmodeltransaction.cpp index 8077156d9e3e..a8a9feb4d08d 100644 --- a/src/qt/walletmodeltransaction.cpp +++ b/src/qt/walletmodeltransaction.cpp @@ -88,7 +88,7 @@ void WalletModelTransaction::reassignAmounts() CAmount WalletModelTransaction::getTotalTransactionAmount() { CAmount totalTransactionAmount = 0; - Q_FOREACH(const SendCoinsRecipient &rcp, recipients) + for (const SendCoinsRecipient &rcp : recipients) { totalTransactionAmount += rcp.amount; } From e81a28604cd99412ab487d41cab3e365c0af486e Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 5 Jul 2019 02:08:44 -0500 Subject: [PATCH 377/987] scripted-diff: Remove PAIRTYPE #10502 -BEGIN VERIFY SCRIPT- sed -i 's/PAIRTYPE(\([^,]*\), \([^\)]*\))/std::pair<\1, \2>/' ./src/*.h ./src/*.cpp ./src/*/*.h ./src/*/*.cpp ./src/*/*/*.h ./src/*/*/*.cpp ; sed -i ':a;N;$!ba;s/#define std::pair std::pair\n//' ./src/utilstrencodings.h ; -END VERIFY SCRIPT- --- src/init.cpp | 2 +- src/qt/addresstablemodel.cpp | 2 +- src/qt/coincontroldialog.cpp | 2 +- src/qt/paymentserver.cpp | 2 +- src/qt/test/paymentservertests.cpp | 2 +- src/qt/transactiondesc.cpp | 4 ++-- src/qt/walletmodel.cpp | 4 ++-- src/rpc/blockchain.cpp | 2 +- src/rpc/net.cpp | 2 +- src/rpc/server.cpp | 2 +- src/script/standard.cpp | 2 +- src/sync.cpp | 10 +++++----- src/utilstrencodings.h | 1 - src/validation.cpp | 6 +++--- src/wallet/rpcwallet.cpp | 4 ++-- src/wallet/wallet.cpp | 16 ++++++++-------- 16 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index f30e91b7e563..43e60e19bd72 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -746,7 +746,7 @@ void CleanupBlockRevFiles() // keeping a separate counter. Once we hit a gap (or if 0 doesn't exist) // start removing block files. int nContigCounter = 0; - for (const PAIRTYPE(std::string, fs::path)& item : mapBlockFiles) { + for (const std::pair& item : mapBlockFiles) { if (atoi(item.first) == nContigCounter) { nContigCounter++; continue; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 7f452faee6db..9c8b03992a4c 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -82,7 +82,7 @@ class AddressTablePriv cachedAddressTable.clear(); { LOCK(wallet->cs_wallet); - for (const PAIRTYPE(CTxDestination, CAddressBookData)& item : wallet->mapAddressBook) + for (const std::pair& item : wallet->mapAddressBook) { const CBitcoinAddress& address = item.first; bool fMine = IsMine(*wallet, address.Get()); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 9b045277c0fd..5f4cc14dbd79 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -672,7 +672,7 @@ void CoinControlDialog::updateView() std::map > mapCoins; model->listCoins(mapCoins); - for (const PAIRTYPE(QString, std::vector)& coins : mapCoins) { + for (const std::pair>& coins : mapCoins) { CCoinControlWidgetItem *itemWalletAddress = new CCoinControlWidgetItem(); itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); QString sWalletAddress = coins.first; diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp index 03d6f1d42375..436df9f67d3a 100644 --- a/src/qt/paymentserver.cpp +++ b/src/qt/paymentserver.cpp @@ -556,7 +556,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen QList > sendingTos = request.getPayTo(); QStringList addresses; - for (const PAIRTYPE(CScript, CAmount)& sendingTo : sendingTos) { + for (const std::pair& sendingTo : sendingTos) { // Extract and check destination addresses CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) { diff --git a/src/qt/test/paymentservertests.cpp b/src/qt/test/paymentservertests.cpp index e812c5c38883..b9a8ad6e280d 100644 --- a/src/qt/test/paymentservertests.cpp +++ b/src/qt/test/paymentservertests.cpp @@ -196,7 +196,7 @@ void PaymentServerTests::paymentServerTests() QVERIFY(r.paymentRequest.IsInitialized()); // Extract address and amount from the request QList > sendingTos = r.paymentRequest.getPayTo(); - for (const PAIRTYPE(CScript, CAmount)& sendingTo : sendingTos) { + for (const std::pair& sendingTo : sendingTos) { CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false); diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 5f5b6bd25dea..a3d8706c78a7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -261,14 +261,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "" + tr("Transaction total size") + ": " + QString::number(wtx.tx->GetTotalSize()) + " bytes
    "; // Message from normal dash:URI (dash:XyZ...?message=example) - for (const PAIRTYPE(std::string, std::string)& r : wtx.vOrderForm) + for (const std::pair& r : wtx.vOrderForm) if (r.first == "Message") strHTML += "
    " + tr("Message") + ":
    " + GUIUtil::HtmlEscape(r.second, true) + "
    "; // // PaymentRequest info: // - for (const PAIRTYPE(std::string, std::string)& r : wtx.vOrderForm) + for (const std::pair& r : wtx.vOrderForm) { if (r.first == "PaymentRequest") { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 748f65ee5c71..4d2ef994ad26 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -768,8 +768,8 @@ void WalletModel::listProTxCoins(std::vector& vOutpts) void WalletModel::loadReceiveRequests(std::vector& vReceiveRequests) { LOCK(wallet->cs_wallet); - for (const PAIRTYPE(CTxDestination, CAddressBookData)& item : wallet->mapAddressBook) - for (const PAIRTYPE(std::string, std::string)& item2 : item.second.destdata) + for (const std::pair& item : wallet->mapAddressBook) + for (const std::pair& item2 : item.second.destdata) if (item2.first.size() > 2 && item2.first.substr(0,2) == "rr") // receive request vReceiveRequests.push_back(item2.second); } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a5350626e0ee..73ce295ea418 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1512,7 +1512,7 @@ UniValue getchaintips(const JSONRPCRequest& request) std::set setOrphans; std::set setPrevs; - for (const PAIRTYPE(const uint256, CBlockIndex*)& item : mapBlockIndex) + for (const std::pair& item : mapBlockIndex) { if (!chainActive.Contains(item.second)) { setOrphans.insert(item.second); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 4f94b2cfd616..5396e548c97d 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -475,7 +475,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request) UniValue localAddresses(UniValue::VARR); { LOCK(cs_mapLocalHost); - for (const PAIRTYPE(CNetAddr, LocalServiceInfo) &item : mapLocalHost) + for (const std::pair &item : mapLocalHost) { UniValue rec(UniValue::VOBJ); rec.push_back(Pair("address", item.first.ToString())); diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 5a41a12d8fb0..241c456f344c 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -233,7 +233,7 @@ std::string CRPCTable::help(const std::string& strCommand, const std::string& st jreq.fHelp = true; jreq.params = UniValue(); - for (const PAIRTYPE(std::string, const CRPCCommand*)& command : vCommands) + for (const std::pair& command : vCommands) { const CRPCCommand *pcmd = command.second; std::string strMethod = pcmd->name; diff --git a/src/script/standard.cpp b/src/script/standard.cpp index 128513f654f4..470bdb4c6c23 100644 --- a/src/script/standard.cpp +++ b/src/script/standard.cpp @@ -76,7 +76,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& tplate : mTemplates) { const CScript& script2 = tplate.second; vSolutionsRet.clear(); diff --git a/src/sync.cpp b/src/sync.cpp index 092b8df17f5f..785b4f07cfd4 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -77,7 +77,7 @@ static void potential_deadlock_detected(const std::pair& mismatch, std::string strOutput = ""; strOutput += "POTENTIAL DEADLOCK DETECTED\n"; strOutput += "Previous lock order was:\n"; - for (const PAIRTYPE(void*, CLockLocation) & i : s2) { + for (const std::pair & i : s2) { if (i.first == mismatch.first) { strOutput += " (1)"; } @@ -87,7 +87,7 @@ static void potential_deadlock_detected(const std::pair& mismatch, strOutput += strprintf(" %s\n", i.second.ToString().c_str()); } strOutput += "Current lock order is:\n"; - for (const PAIRTYPE(void*, CLockLocation) & i : s1) { + for (const std::pair & i : s1) { if (i.first == mismatch.first) { strOutput += " (1)"; } @@ -112,7 +112,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry) (*lockstack).push_back(std::make_pair(c, locklocation)); - for (const PAIRTYPE(void*, CLockLocation) & i : (*lockstack)) { + for (const std::pair & i : (*lockstack)) { if (i.first == c) break; @@ -146,14 +146,14 @@ void LeaveCritical() std::string LocksHeld() { std::string result; - for (const PAIRTYPE(void*, CLockLocation) & i : *lockstack) + for (const std::pair & i : *lockstack) result += i.second.ToString() + std::string("\n"); return result; } void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) { - for (const PAIRTYPE(void*, CLockLocation) & i : *lockstack) + for (const std::pair & i : *lockstack) if (i.first == cs) return; fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str()); diff --git a/src/utilstrencodings.h b/src/utilstrencodings.h index 082332a265eb..a35cea289caf 100644 --- a/src/utilstrencodings.h +++ b/src/utilstrencodings.h @@ -18,7 +18,6 @@ #define UBEGIN(a) ((unsigned char*)&(a)) #define UEND(a) ((unsigned char*)&((&(a))[1])) #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0])) -#define PAIRTYPE(t1, t2) std::pair /** Used by SanitizeString() */ enum SafeChars diff --git a/src/validation.cpp b/src/validation.cpp index 2509da14dd9d..b8f16aabd6e8 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3929,7 +3929,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) // Calculate nChainWork std::vector > vSortedByHeight; vSortedByHeight.reserve(mapBlockIndex.size()); - for (const PAIRTYPE(uint256, CBlockIndex*)& item : mapBlockIndex) + for (const std::pair& item : mapBlockIndex) { CBlockIndex* pindex = item.second; vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex)); @@ -3940,7 +3940,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) } } sort(vSortedByHeight.begin(), vSortedByHeight.end()); - for (const PAIRTYPE(int, CBlockIndex*)& item : vSortedByHeight) + for (const std::pair& item : vSortedByHeight) { CBlockIndex* pindex = item.second; pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex); @@ -3989,7 +3989,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) // Check presence of blk files LogPrintf("Checking all blk files are present...\n"); std::set setBlkDataFiles; - for (const PAIRTYPE(uint256, CBlockIndex*)& item : mapBlockIndex) + for (const std::pair& item : mapBlockIndex) { CBlockIndex* pindex = item.second; if (pindex->nStatus & BLOCK_HAVE_DATA) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0e668d7268df..9b9b31fc93ae 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -92,7 +92,7 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) entry.push_back(Pair("time", wtx.GetTxTime())); entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived)); - for (const PAIRTYPE(std::string, std::string)& item : wtx.mapValue) + for (const std::pair& item : wtx.mapValue) entry.push_back(Pair(item.first, item.second)); } @@ -1652,7 +1652,7 @@ UniValue listaccounts(const JSONRPCRequest& request) mapAccountBalances[entry.strAccount] += entry.nCreditDebit; UniValue ret(UniValue::VOBJ); - for (const PAIRTYPE(std::string, CAmount)& accountBalance : mapAccountBalances) { + for (const std::pair& accountBalance : mapAccountBalances) { ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second))); } return ret; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 065dadf7afe8..748efbf6ad1c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1003,7 +1003,7 @@ void CWallet::MarkDirty() { { LOCK(cs_wallet); - for (PAIRTYPE(const uint256, CWalletTx)& item : mapWallet) + for (std::pair& item : mapWallet) item.second.MarkDirty(); } @@ -1885,7 +1885,7 @@ void CWallet::ReacceptWalletTransactions() std::map mapSorted; // Sort pending wallet transactions based on their initial wallet insertion order - for (PAIRTYPE(const uint256, CWalletTx)& item : mapWallet) + for (std::pair& item : mapWallet) { const uint256& wtxid = item.first; CWalletTx& wtx = item.second; @@ -1899,7 +1899,7 @@ void CWallet::ReacceptWalletTransactions() } // Try to add wallet transactions to memory pool - for (PAIRTYPE(const int64_t, CWalletTx*)& item : mapSorted) + for (std::pair& item : mapSorted) { CWalletTx& wtx = *(item.second); @@ -2235,7 +2235,7 @@ std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime, CCon LOCK(cs_wallet); // Sort them in chronological order std::multimap mapSorted; - for (PAIRTYPE(const uint256, CWalletTx)& item : mapWallet) + for (std::pair& item : mapWallet) { CWalletTx& wtx = item.second; // Don't rebroadcast if newer than nTime: @@ -2243,7 +2243,7 @@ std::vector CWallet::ResendWalletTransactionsBefore(int64_t nTime, CCon continue; mapSorted.insert(std::make_pair(wtx.nTimeReceived, &wtx)); } - for (PAIRTYPE(const unsigned int, CWalletTx*)& item : mapSorted) + for (std::pair& item : mapSorted) { CWalletTx& wtx = *item.second; if (wtx.RelayWalletTransaction(connman)) @@ -3987,7 +3987,7 @@ bool CWallet::DelAddressBook(const CTxDestination& address) // Delete destdata tuples associated with address std::string strAddress = CBitcoinAddress(address).ToString(); - for (const PAIRTYPE(std::string, std::string) &item : mapAddressBook[address].destdata) + for (const std::pair &item : mapAddressBook[address].destdata) { CWalletDB(*dbw).EraseDestData(strAddress, item.first); } @@ -4374,7 +4374,7 @@ std::set CWallet::GetAccountAddresses(const std::string& strAcco { LOCK(cs_wallet); std::set result; - for (const PAIRTYPE(CTxDestination, CAddressBookData)& item : mapAddressBook) + for (const std::pair& item : mapAddressBook) { const CTxDestination& address = item.first; const std::string& strName = item.second.name; @@ -5232,7 +5232,7 @@ bool AutoBackupWallet(CWallet* wallet, const std::string& strWalletFile_, std::s // Loop backward through backup files and keep the N newest ones (1 <= N <= 10) int counter = 0; - BOOST_REVERSE_FOREACH(PAIRTYPE(const std::time_t, fs::path) file, folder_set) + BOOST_REVERSE_FOREACH(std::pair file, folder_set) { counter++; if (counter > nWalletBackups) From 0cb552a20bbba1827ad9001cc4bcb07a607b56bc Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 14 Jun 2017 15:22:08 +0200 Subject: [PATCH 378/987] Merge #10377: Use rdrand as entropy source on supported platforms cb24c85 Use rdrand as entropy source on supported platforms (Pieter Wuille) Tree-SHA512: c42eaa01a14e6bc097c70b6bf8540d61854c2f76cb32be69c2a3c411a126f7b4bf4a4486e4493c4cc367cc689319abde0d4adb799d29a54fd3e81767ce0766fc --- src/init.cpp | 1 + src/random.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++ src/random.h | 3 ++ src/test/test_dash.cpp | 1 + 4 files changed, 73 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 43e60e19bd72..9d4c92fb879f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1463,6 +1463,7 @@ bool AppInitSanityChecks() // ********************************************************* Step 4: sanity checks // Initialize elliptic curve code + RandomInit(); ECC_Start(); globalVerifyHandle.reset(new ECCVerifyHandle()); diff --git a/src/random.cpp b/src/random.cpp index 0668966756f0..60756c9a0178 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -65,6 +65,64 @@ static inline int64_t GetPerformanceCounter() #endif } + +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) +static std::atomic hwrand_initialized{false}; +static bool rdrand_supported = false; +static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; +static void RDRandInit() +{ + //! When calling cpuid function #1, ecx register will have this set if RDRAND is available. + // Avoid clobbering ebx, as that is used for PIC on x86. + uint32_t eax, tmp, ecx, edx; + __asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1)); + if (ecx & CPUID_F1_ECX_RDRAND) { + LogPrintf("Using RdRand as entropy source\n"); + rdrand_supported = true; + } + hwrand_initialized.store(true); +} +#else +static void RDRandInit() {} +#endif + +static bool GetHWRand(unsigned char* ent32) { +#if defined(__x86_64__) || defined(__amd64__) || defined(__i386__) + assert(hwrand_initialized.load(std::memory_order_relaxed)); + if (rdrand_supported) { + uint8_t ok; + // Not all assemblers support the rdrand instruction, write it in hex. +#ifdef __i386__ + for (int iter = 0; iter < 4; ++iter) { + uint32_t r1, r2; + __asm__ volatile (".byte 0x0f, 0xc7, 0xf0;" // rdrand %eax + ".byte 0x0f, 0xc7, 0xf2;" // rdrand %edx + "setc %2" : + "=a"(r1), "=d"(r2), "=q"(ok) :: "cc"); + if (!ok) return false; + WriteLE32(ent32 + 8 * iter, r1); + WriteLE32(ent32 + 8 * iter + 4, r2); + } +#else + uint64_t r1, r2, r3, r4; + __asm__ volatile (".byte 0x48, 0x0f, 0xc7, 0xf0, " // rdrand %rax + "0x48, 0x0f, 0xc7, 0xf3, " // rdrand %rbx + "0x48, 0x0f, 0xc7, 0xf1, " // rdrand %rcx + "0x48, 0x0f, 0xc7, 0xf2; " // rdrand %rdx + "setc %4" : + "=a"(r1), "=b"(r2), "=c"(r3), "=d"(r4), "=q"(ok) :: "cc"); + if (!ok) return false; + WriteLE64(ent32, r1); + WriteLE64(ent32 + 8, r2); + WriteLE64(ent32 + 16, r3); + WriteLE64(ent32 + 24, r4); +#endif + return true; + } +#endif + return false; +} + void RandAddSeed() { // Seed with CPU performance counter @@ -255,6 +313,11 @@ void GetStrongRandBytes(unsigned char* out, int num) GetOSRand(buf); hasher.Write(buf, 32); + // Third source: HW RNG, if available. + if (GetHWRand(buf)) { + hasher.Write(buf, 32); + } + // Combine with and update state { std::unique_lock lock(cs_rng_state); @@ -392,3 +455,8 @@ FastRandomContext::FastRandomContext(bool fDeterministic) : requires_seed(!fDete uint256 seed; rng.SetKey(seed.begin(), 32); } + +void RandomInit() +{ + RDRandInit(); +} diff --git a/src/random.h b/src/random.h index 306c9355830b..72659e12b115 100644 --- a/src/random.h +++ b/src/random.h @@ -150,4 +150,7 @@ void GetOSRand(unsigned char *ent32); */ bool Random_SanityCheck(); +/** Initialize the RNG. */ +void RandomInit(); + #endif // BITCOIN_RANDOM_H diff --git a/src/test/test_dash.cpp b/src/test/test_dash.cpp index 12fab1446669..a440feee6cef 100644 --- a/src/test/test_dash.cpp +++ b/src/test/test_dash.cpp @@ -38,6 +38,7 @@ extern void noui_connect(); BasicTestingSetup::BasicTestingSetup(const std::string& chainName) { + RandomInit(); ECC_Start(); BLSInit(); SetupEnvironment(); From 61ca895c4e92eab0d59e09ee2ec69050b01121eb Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 14 Jun 2017 15:27:24 +0200 Subject: [PATCH 379/987] Merge #10551: [Tests] Wallet encryption functional tests ec98b78 Tests for wallet encryption stuff (Andrew Chow) Tree-SHA512: 176f146dee87f7eaf6de689598ddf257264bb77c2f8c0f9b00276e0dd956327463fb50403a32916f00765d2b2a588c1692a600b36bb3c9e7fa2f18d7cc3b4bc0 --- test/functional/test_runner.py | 1 + test/functional/wallet-encryption.py | 66 ++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100755 test/functional/wallet-encryption.py diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 5fabd71e7648..574fcdb42dc3 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -124,6 +124,7 @@ 'p2p-compactblocks.py', 'sporks.py', 'p2p-fingerprint.py', + 'wallet-encryption.py', ] EXTENDED_SCRIPTS = [ diff --git a/test/functional/wallet-encryption.py b/test/functional/wallet-encryption.py new file mode 100755 index 000000000000..33872e3c9465 --- /dev/null +++ b/test/functional/wallet-encryption.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# Copyright (c) 2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test Wallet encryption""" + +import time + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, + assert_raises_jsonrpc, + bitcoind_processes, + BITCOIND_PROC_WAIT_TIMEOUT, +) + +class WalletEncryptionTest(BitcoinTestFramework): + + def __init__(self): + super().__init__() + self.setup_clean_chain = True + self.num_nodes = 1 + + def run_test(self): + passphrase = "WalletPassphrase" + passphrase2 = "SecondWalletPassphrase" + + # Make sure the wallet isn't encrypted first + address = self.nodes[0].getnewaddress() + privkey = self.nodes[0].dumpprivkey(address) + assert_equal(privkey[:1], "c") + assert_equal(len(privkey), 52) + + # Encrypt the wallet + self.nodes[0].encryptwallet(passphrase) + bitcoind_processes[0].wait(timeout=BITCOIND_PROC_WAIT_TIMEOUT) + self.nodes[0] = self.start_node(0, self.options.tmpdir) + + # Test that the wallet is encrypted + assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address) + + # Check that walletpassphrase works + self.nodes[0].walletpassphrase(passphrase, 2) + assert_equal(privkey, self.nodes[0].dumpprivkey(address)) + + # Check that the timeout is right + time.sleep(2) + assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address) + + # Test wrong passphrase + assert_raises_jsonrpc(-14, "wallet passphrase entered was incorrect", self.nodes[0].walletpassphrase, passphrase + "wrong", 10) + + # Test walletlock + self.nodes[0].walletpassphrase(passphrase, 84600) + assert_equal(privkey, self.nodes[0].dumpprivkey(address)) + self.nodes[0].walletlock() + assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].dumpprivkey, address) + + # Test passphrase changes + self.nodes[0].walletpassphrasechange(passphrase, passphrase2) + assert_raises_jsonrpc(-14, "wallet passphrase entered was incorrect", self.nodes[0].walletpassphrase, passphrase, 10) + self.nodes[0].walletpassphrase(passphrase2, 10) + assert_equal(privkey, self.nodes[0].dumpprivkey(address)) + +if __name__ == '__main__': + WalletEncryptionTest().main() From ab02a43357c454f7b8b9e382a2568227e13c1319 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 14 Jun 2017 15:36:56 +0200 Subject: [PATCH 380/987] Merge #9738: gettxoutproof() should return consistent result 6294f32 gettxoutproof() should return consistent result (John Newbery) Tree-SHA512: 1c36f78ea07a3bdde09e9494207b4372d54bcd94ed2d56e339e78281f6693e26a93e4c3123453d5c0f6e994d0069d5a1c806786c4af71864f87ea4841611c379 --- src/rpc/rawtransaction.cpp | 12 ++++++++---- test/functional/merkle_blocks.py | 25 +++++++++++++++---------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 676a9521b7e6..318b601c1b0e 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -265,9 +265,13 @@ UniValue gettxoutproof(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); pblockindex = mapBlockIndex[hashBlock]; } else { - const Coin& coin = AccessByTxid(*pcoinsTip, oneTxid); - if (!coin.IsSpent() && coin.nHeight > 0 && coin.nHeight <= chainActive.Height()) { - pblockindex = chainActive[coin.nHeight]; + // Loop through txids and try to find which block they're in. Exit loop once a block is found. + for (const auto& tx : setTxids) { + const Coin& coin = AccessByTxid(*pcoinsTip, tx); + if (!coin.IsSpent()) { + pblockindex = chainActive[coin.nHeight]; + break; + } } } @@ -290,7 +294,7 @@ UniValue gettxoutproof(const JSONRPCRequest& request) if (setTxids.count(tx->GetHash())) ntxFound++; if (ntxFound != setTxids.size()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "(Not all) transactions not found in specified block"); + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Not all transactions found in specified or retrieved block"); CDataStream ssMB(SER_NETWORK, PROTOCOL_VERSION); CMerkleBlock mb(block, setTxids); diff --git a/test/functional/merkle_blocks.py b/test/functional/merkle_blocks.py index 564a4b5b0130..d9d3e17f9472 100755 --- a/test/functional/merkle_blocks.py +++ b/test/functional/merkle_blocks.py @@ -40,7 +40,8 @@ def run_test(self): txid1 = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransaction(tx1)["hex"]) tx2 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 500 - tx_fee}) txid2 = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransaction(tx2)["hex"]) - assert_raises(JSONRPCException, self.nodes[0].gettxoutproof, [txid1]) + # This will raise an exception because the transaction is not yet in a block + assert_raises_jsonrpc(-5, "Transaction not yet in block", self.nodes[0].gettxoutproof, [txid1]) self.nodes[0].generate(1) blockhash = self.nodes[0].getblockhash(chain_height + 1) @@ -57,7 +58,7 @@ def run_test(self): txin_spent = self.nodes[1].listunspent(1).pop() tx3 = self.nodes[1].createrawtransaction([txin_spent], {self.nodes[0].getnewaddress(): 500 - tx_fee*2}) - self.nodes[0].sendrawtransaction(self.nodes[1].signrawtransaction(tx3)["hex"]) + txid3 = self.nodes[0].sendrawtransaction(self.nodes[1].signrawtransaction(tx3)["hex"]) self.nodes[0].generate(1) self.sync_all() @@ -66,17 +67,21 @@ def run_test(self): # We can't find the block from a fully-spent tx # Doesn't apply to Dash Core - we have txindex always on - # assert_raises(JSONRPCException, self.nodes[2].gettxoutproof, [txid_spent]) - # ...but we can if we specify the block + # assert_raises_jsonrpc(-5, "Transaction not yet in block", self.nodes[2].gettxoutproof, [txid_spent]) + # We can get the proof if we specify the block assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent]) - # ...or if the first tx is not fully-spent + # We can't get the proof if we specify a non-existent block + assert_raises_jsonrpc(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000") + # We can get the proof if the transaction is unspent assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_unspent])), [txid_unspent]) - try: - assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1, txid2])), txlist) - except JSONRPCException: - assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid2, txid1])), txlist) - # ...or if we have a -txindex + # We can get the proof if we provide a list of transactions and one of them is unspent. The ordering of the list should not matter. + assert_equal(sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1, txid2]))), sorted(txlist)) + assert_equal(sorted(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid2, txid1]))), sorted(txlist)) + # We can always get a proof if we have a -txindex assert_equal(self.nodes[2].verifytxoutproof(self.nodes[3].gettxoutproof([txid_spent])), [txid_spent]) + # We can't get a proof if we specify transactions from different blocks + assert_raises_jsonrpc(-5, "Not all transactions found in specified or retrieved block", self.nodes[2].gettxoutproof, [txid1, txid3]) + if __name__ == '__main__': MerkleBlockTest().main() From c520de2396d82e77e0c8558ad1ccd9d92010a14f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 14 Jun 2017 16:00:39 +0200 Subject: [PATCH 381/987] Merge #9895: Turn TryCreateDirectory() into TryCreateDirectories() 1d1ea9f Turn TryCreateDirectory() into TryCreateDirectories() (Marko Bencun) Tree-SHA512: 49a524167bcf66e351a964c88d09cb3bcee12769a32da83410e3ba649fa4bcdbf0478d41e4d09bb55adb9b3f122e742271db6feb30bbafe2a7973542b5f10f79 --- src/dbwrapper.cpp | 2 +- src/init.cpp | 2 -- src/qt/intro.cpp | 2 +- src/util.cpp | 8 ++++---- src/util.h | 2 +- src/wallet/db.cpp | 2 +- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/dbwrapper.cpp b/src/dbwrapper.cpp index 638d669c4c0a..eb6d5ecb5fd6 100644 --- a/src/dbwrapper.cpp +++ b/src/dbwrapper.cpp @@ -108,7 +108,7 @@ CDBWrapper::CDBWrapper(const fs::path& path, size_t nCacheSize, bool fMemory, bo leveldb::Status result = leveldb::DestroyDB(path.string(), options); dbwrapper_private::HandleError(result); } - TryCreateDirectory(path); + TryCreateDirectories(path); LogPrintf("Opening LevelDB in %s\n", path.string()); } leveldb::Status status = leveldb::DB::Open(options, path.string(), &pdb); diff --git a/src/init.cpp b/src/init.cpp index 9d4c92fb879f..dbd7bf09e275 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1762,8 +1762,6 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) fReindex = gArgs.GetBoolArg("-reindex", false); bool fReindexChainState = gArgs.GetBoolArg("-reindex-chainstate", false); - fs::create_directories(GetDataDir() / "blocks"); - // cache size calculations int64_t nTotalCache = (gArgs.GetArg("-dbcache", nDefaultDbCache) << 20); nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 1c7251f3c747..6ec5da6d03a9 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -217,7 +217,7 @@ bool Intro::pickDataDirectory() } dataDir = intro.getDataDirectory(); try { - TryCreateDirectory(GUIUtil::qstringToBoostPath(dataDir)); + TryCreateDirectories(GUIUtil::qstringToBoostPath(dataDir)); break; } catch (const fs::filesystem_error&) { QMessageBox::critical(0, tr(PACKAGE_NAME), diff --git a/src/util.cpp b/src/util.cpp index 581b1faf48d2..16976cf6c357 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -757,21 +757,21 @@ bool RenameOver(fs::path src, fs::path dest) } /** - * Ignores exceptions thrown by Boost's create_directory if the requested directory exists. + * Ignores exceptions thrown by Boost's create_directories if the requested directory exists. * Specifically handles case where path p exists, but it wasn't possible for the user to * write to the parent directory. */ -bool TryCreateDirectory(const fs::path& p) +bool TryCreateDirectories(const fs::path& p) { try { - return fs::create_directory(p); + return fs::create_directories(p); } catch (const fs::filesystem_error&) { if (!fs::exists(p) || !fs::is_directory(p)) throw; } - // create_directory didn't create the directory, it had to have existed already + // create_directories didn't create the directory, it had to have existed already return false; } diff --git a/src/util.h b/src/util.h index a38c010efbc9..41d14e4d4f7f 100644 --- a/src/util.h +++ b/src/util.h @@ -205,7 +205,7 @@ bool TruncateFile(FILE *file, unsigned int length); int RaiseFileDescriptorLimit(int nMinFD); void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length); bool RenameOver(fs::path src, fs::path dest); -bool TryCreateDirectory(const fs::path& p); +bool TryCreateDirectories(const fs::path& p); fs::path GetDefaultDataDir(); const fs::path &GetDataDir(bool fNetSpecific = true); fs::path GetBackupsDir(); diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 24f805562dc1..1ccae839253e 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -74,7 +74,7 @@ bool CDBEnv::Open(const fs::path& pathIn) strPath = pathIn.string(); fs::path pathLogDir = pathIn / "database"; - TryCreateDirectory(pathLogDir); + TryCreateDirectories(pathLogDir); fs::path pathErrorFile = pathIn / "db.log"; LogPrintf("CDBEnv::Open: LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string()); From 3bae86b62d0f0bb2ad4bcf51e6ca8e8adee5c09c Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 15 Jun 2017 12:51:20 +0200 Subject: [PATCH 382/987] Merge #10582: Pass in smart fee slider value to coin control dialog e9cd778 Pass in smart fee slider value to coin control dialog (Alex Morcos) Tree-SHA512: 3899c3eb89b06e9cc842b33fabcce40a84fcc3a88ac2b02861f63419925312ac2a9f632567c02b0a060f5c5cd55f337e35e99b80535d1c1b8fcb7fd0c539f3c0 --- src/qt/coincontroldialog.cpp | 4 ++-- src/qt/sendcoinsdialog.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 5f4cc14dbd79..ef5068348bb6 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -549,7 +549,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytes -= 34; // Fee - nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, ::mempool, ::feeEstimator); + nPayFee = CWallet::GetMinimumFee(nBytes, coinControl->nConfirmTarget, ::mempool, ::feeEstimator); if (nPayAmount > 0) { @@ -633,7 +633,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) if (payTxFee.GetFeePerK() > 0) dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000; else { - dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(nTxConfirmTarget, NULL, ::mempool).GetFeePerK()) / 1000; + dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), ::feeEstimator.estimateSmartFee(coinControl->nConfirmTarget, NULL, ::mempool).GetFeePerK()) / 1000; } QString toolTip4 = tr("Can vary +/- %1 duff(s) per input.").arg(dFeeVary); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 729d7b49e5f8..9de6a0d0ddd1 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -912,6 +912,12 @@ void SendCoinsDialog::coinControlUpdateLabels() // set pay amounts CoinControlDialog::payAmounts.clear(); CoinControlDialog::fSubtractFeeFromAmount = false; + if (ui->radioSmartFee->isChecked()) { + CoinControlDialog::coinControl->nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; + } else { + CoinControlDialog::coinControl->nConfirmTarget = model->getDefaultConfirmTarget(); + } + for(int i = 0; i < ui->entries->count(); ++i) { SendCoinsEntry *entry = qobject_cast(ui->entries->itemAt(i)->widget()); From 8c4e351c8a5f1b27c7faa26af0a5124a080e0b0f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 16 Jun 2017 15:02:00 -0700 Subject: [PATCH 383/987] Merge #10602: Make clang-format use C++11 features (e.g. A> instead of A >) 131a8ceb7 Make clang-format use C++11 features (e.g. A> instead of A >) (practicalswift) Tree-SHA512: e3c0ee683b654eae638deb41c52cf3187fa958dc5fa67778eaf8a83946b63f5b1d24c47bb965eaa910e3fcdcaf9eebf461eb3fc8e3a73ebaf03c7904521fda00 --- src/.clang-format | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/.clang-format b/src/.clang-format index 1e8222754462..f1113e635362 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -49,6 +49,6 @@ SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false -Standard: Cpp03 +Standard: Cpp11 TabWidth: 8 UseTab: Never From 0647ea656454d2cdf107bf97e9f44026010f41be Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 16 Jun 2017 16:34:34 -0700 Subject: [PATCH 384/987] Merge #10587: Net: Fix resource leak in ReadBinaryFile(...) f2fb132cb Net: Fix resource leak in ReadBinaryFile(...) (practicalswift) Tree-SHA512: 879b9334d8bb681fa4b6f96d8ecb54e2a8948065f7be5fe7880131479c813602fc9d4a4314f043e6591e1aed50ffafa7c247362a9cdeb049b0721170e227b89a --- src/torcontrol.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 944b4e6f48d2..3f460ae8c71e 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -376,8 +376,10 @@ static std::pair ReadBinaryFile(const fs::path &filename, size while ((n=fread(buffer, 1, sizeof(buffer), f)) > 0) { // Check for reading errors so we don't return any data if we couldn't // read the entire file (or up to maxsize) - if (ferror(f)) + if (ferror(f)) { + fclose(f); return std::make_pair(false,""); + } retval.append(buffer, buffer+n); if (retval.size() > maxsize) break; From 5ac6d7c4e5f76bd7f5c7bdc8d23623d750b41103 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 16 Jun 2017 17:36:22 -0700 Subject: [PATCH 385/987] Merge #10614: random: fix crash on some 64bit platforms 9af207c81 random: fix crash on some 64bit platforms (Cory Fields) Tree-SHA512: c9516b69bec224c7e650dfc7c50f04cdd93a1006d515699bc64a311a03662d4ad33a834861194a1649ed212b37fb50aadfb004954cdf8b9bc1dc82f3ea962897 --- src/random.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/random.cpp b/src/random.cpp index 60756c9a0178..b171b3dabfed 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -72,10 +72,16 @@ static bool rdrand_supported = false; static constexpr uint32_t CPUID_F1_ECX_RDRAND = 0x40000000; static void RDRandInit() { - //! When calling cpuid function #1, ecx register will have this set if RDRAND is available. + uint32_t eax, ecx, edx; +#if defined(__i386__) && ( defined(__PIC__) || defined(__PIE__)) // Avoid clobbering ebx, as that is used for PIC on x86. - uint32_t eax, tmp, ecx, edx; + uint32_t tmp; __asm__ ("mov %%ebx, %1; cpuid; mov %1, %%ebx": "=a"(eax), "=g"(tmp), "=c"(ecx), "=d"(edx) : "a"(1)); +#else + uint32_t ebx; + __asm__ ("cpuid": "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(1)); +#endif + //! When calling cpuid function #1, ecx register will have this set if RDRAND is available. if (ecx & CPUID_F1_ECX_RDRAND) { LogPrintf("Using RdRand as entropy source\n"); rdrand_supported = true; From e1a146d955016a8bd825146e0e5921dbf68ebb1c Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 18 Jun 2017 14:07:29 +0200 Subject: [PATCH 386/987] Merge #10592: [trivial] fix indentation for ArgsManager class 7810993 [trivial] fix indentation for ArgsManager class (John Newbery) Tree-SHA512: 3d24fa94ba49ad73383ca8077776492bd75f1c2158c835c1d55b4be4787f107c2de5336173e083a5585df21ef053614628fe4fe6ddf2c05df567177445661b7b --- src/util.h | 111 +++++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/src/util.h b/src/util.h index 41d14e4d4f7f..066614c3e47d 100644 --- a/src/util.h +++ b/src/util.h @@ -241,62 +241,63 @@ class ArgsManager void ParseParameters(int argc, const char*const argv[]); void ReadConfigFile(const std::string& confPath); std::vector GetArgs(const std::string& strArg); -/** - * Return true if the given argument has been manually set - * - * @param strArg Argument to get (e.g. "-foo") - * @return true if the argument has been set - */ -bool IsArgSet(const std::string& strArg); - -/** - * Return string argument or default value - * - * @param strArg Argument to get (e.g. "-foo") - * @param default (e.g. "1") - * @return command-line argument or default value - */ -std::string GetArg(const std::string& strArg, const std::string& strDefault); - -/** - * Return integer argument or default value - * - * @param strArg Argument to get (e.g. "-foo") - * @param default (e.g. 1) - * @return command-line argument (0 if invalid number) or default value - */ -int64_t GetArg(const std::string& strArg, int64_t nDefault); - -/** - * Return boolean argument or default value - * - * @param strArg Argument to get (e.g. "-foo") - * @param default (true or false) - * @return command-line argument or default value - */ -bool GetBoolArg(const std::string& strArg, bool fDefault); - -/** - * Set an argument if it doesn't already have a value - * - * @param strArg Argument to set (e.g. "-foo") - * @param strValue Value (e.g. "1") - * @return true if argument gets set, false if it already had a value - */ -bool SoftSetArg(const std::string& strArg, const std::string& strValue); - -/** - * Set a boolean argument if it doesn't already have a value - * - * @param strArg Argument to set (e.g. "-foo") - * @param fValue Value (e.g. false) - * @return true if argument gets set, false if it already had a value - */ -bool SoftSetBoolArg(const std::string& strArg, bool fValue); -// Forces an arg setting. Called by SoftSetArg() if the arg hasn't already -// been set. Also called directly in testing. -void ForceSetArg(const std::string& strArg, const std::string& strValue); + /** + * Return true if the given argument has been manually set + * + * @param strArg Argument to get (e.g. "-foo") + * @return true if the argument has been set + */ + bool IsArgSet(const std::string& strArg); + + /** + * Return string argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (e.g. "1") + * @return command-line argument or default value + */ + std::string GetArg(const std::string& strArg, const std::string& strDefault); + + /** + * Return integer argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (e.g. 1) + * @return command-line argument (0 if invalid number) or default value + */ + int64_t GetArg(const std::string& strArg, int64_t nDefault); + + /** + * Return boolean argument or default value + * + * @param strArg Argument to get (e.g. "-foo") + * @param default (true or false) + * @return command-line argument or default value + */ + bool GetBoolArg(const std::string& strArg, bool fDefault); + + /** + * Set an argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param strValue Value (e.g. "1") + * @return true if argument gets set, false if it already had a value + */ + bool SoftSetArg(const std::string& strArg, const std::string& strValue); + + /** + * Set a boolean argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param fValue Value (e.g. false) + * @return true if argument gets set, false if it already had a value + */ + bool SoftSetBoolArg(const std::string& strArg, bool fValue); + + // Forces an arg setting. Called by SoftSetArg() if the arg hasn't already + // been set. Also called directly in testing. + void ForceSetArg(const std::string& strArg, const std::string& strValue); void ForceSetMultiArgs(const std::string& strArg, const std::vector& values); void ForceRemoveArg(const std::string& strArg); }; From aa364bf7af73d3328b4e2352f2b2e3d816f07a8b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 18 Jun 2017 14:13:50 +0200 Subject: [PATCH 387/987] Merge #10555: [tests] various improvements to zmq_test.py 0a4912e [tests] timeout integration tests on travis after 20 minutes (John Newbery) 7c51e9f [tests] destroy zmq context in zmq_tests.py (John Newbery) b1bac1c [tests] in zmq test, timeout if message not received (John Newbery) 5ebd5f9 [tests] tidy up zmq_test.py (John Newbery) 4a0c08f [tests] update zmq test to use correct config.ini file (John Newbery) Tree-SHA512: 5e607af2f2dc5c73fba4b2d3890097580a7525f6a4996c7c78f01822e45e0054fd0a225ea53fce6308804e560cced6de6cf5d16137469dcf100b2e9643e08d03 --- test/functional/test_runner.py | 7 +++- test/functional/zmq_test.py | 65 ++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 574fcdb42dc3..08734e402d08 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -20,6 +20,7 @@ import os import time import shutil +import signal import sys import subprocess import tempfile @@ -85,7 +86,7 @@ 'rawtransactions.py', 'reindex.py', # vv Tests less than 30s vv - "zmq_test.py", + 'zmq_test.py', 'mempool_resurrect_test.py', 'txn_doublespend.py --mineblock', 'txn_clone.py', @@ -404,6 +405,10 @@ def get_next(self): time.sleep(.5) for j in self.jobs: (name, time0, proc, log_out, log_err) = j + if os.getenv('TRAVIS') == 'true' and int(time.time() - time0) > 20 * 60: + # In travis, timeout individual tests after 20 minutes (to stop tests hanging and not + # providing useful output. + proc.send_signal(signal.SIGINT) if proc.poll() is not None: log_out.seek(0), log_err.seek(0) [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index cc357372ebc4..c2b93b68ee69 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -8,15 +8,15 @@ import struct from test_framework.test_framework import BitcoinTestFramework, SkipTest -from test_framework.util import * +from test_framework.util import (assert_equal, + bytes_to_hex_str, + ) class ZMQTest (BitcoinTestFramework): def __init__(self): super().__init__() - self.num_nodes = 4 - - port = 28332 + self.num_nodes = 2 def setup_nodes(self): # Try to import python3-zmq. Skip this test if the import fails. @@ -28,7 +28,7 @@ def setup_nodes(self): # Check that dash has been built with ZMQ enabled config = configparser.ConfigParser() if not self.options.configfile: - self.options.configfile = os.path.dirname(__file__) + "/config.ini" + self.options.configfile = os.path.dirname(__file__) + "/../config.ini" config.read_file(open(self.options.configfile)) if not config["components"].getboolean("ENABLE_ZMQ"): @@ -36,59 +36,66 @@ def setup_nodes(self): self.zmqContext = zmq.Context() self.zmqSubSocket = self.zmqContext.socket(zmq.SUB) + self.zmqSubSocket.set(zmq.RCVTIMEO, 60000) self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock") self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx") - self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port) - self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[ - ['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)], - [], - [], - [] - ]) + ip_address = "tcp://127.0.0.1:28332" + self.zmqSubSocket.connect(ip_address) + extra_args = [['-zmqpubhashtx=%s' % ip_address, '-zmqpubhashblock=%s' % ip_address], []] + self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, extra_args) def run_test(self): - self.sync_all() + try: + self._zmq_test() + finally: + # Destroy the zmq context + self.log.debug("Destroying zmq context") + self.zmqContext.destroy(linger=None) + def _zmq_test(self): genhashes = self.nodes[0].generate(1) self.sync_all() - self.log.info("listen...") + self.log.info("Wait for tx") msg = self.zmqSubSocket.recv_multipart() topic = msg[0] assert_equal(topic, b"hashtx") body = msg[1] msgSequence = struct.unpack(' Date: Tue, 20 Jun 2017 16:19:34 -0700 Subject: [PATCH 388/987] Merge #9549: [net] Avoid possibility of NULL pointer dereference in MarkBlockAsInFlight(...) 95543d874 [net] Avoid possibility of NULL pointer dereference in MarkBlockAsInFlight(...) (practicalswift) Tree-SHA512: 80fd4f2712f20377185bd8d319255f2c54ae47b54c706f7e0d384a0a6ade1465ceb6e2a4a7f7b51987a659524474a954eddf228865ebb3fc513948b5b6d7ab6d --- src/net_processing.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 2488178ace45..24c0cd7d4f9d 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -377,7 +377,9 @@ bool MarkBlockAsInFlight(NodeId nodeid, const uint256& hash, const CBlockIndex * // Short-circuit most stuff in case its from the same node std::map::iterator> >::iterator itInFlight = mapBlocksInFlight.find(hash); if (itInFlight != mapBlocksInFlight.end() && itInFlight->second.first == nodeid) { - *pit = &itInFlight->second.second; + if (pit) { + *pit = &itInFlight->second.second; + } return false; } From 9d336854f73c83684eec587280636b50d1fcc2b8 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 20 Jun 2017 17:52:32 -0700 Subject: [PATCH 389/987] Merge #10503: Use REJECT_DUPLICATE for already known and conflicted txn d9bec888f Use REJECT_DUPLICATE for already known and conflicted txn (Pieter Wuille) Tree-SHA512: adc6dc5caed731c3fd5c8784e8820a074e320360cdb5579c5b9299f9799dd99de60b7382d336ab1909dab8b23e744456d78aa0c3b1c8dd1af3d1b779314cf8fa --- src/validation.cpp | 9 +++++---- src/validation.h | 4 ---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index b8f16aabd6e8..6f96fb56894e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -691,8 +691,9 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool return state.DoS(0, false, REJECT_NONSTANDARD, "non-final"); // is it already in the memory pool? - if (pool.exists(hash)) - return state.Invalid(false, REJECT_ALREADY_KNOWN, "txn-already-in-mempool"); + if (pool.exists(hash)) { + return state.Invalid(false, REJECT_DUPLICATE, "txn-already-in-mempool"); + } llmq::CInstantSendLockPtr conflictLock = llmq::quorumInstantSendManager->GetConflictingLock(tx); if (conflictLock) { @@ -717,7 +718,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool const CTransaction *ptxConflicting = itConflicting->second; // Transaction conflicts with mempool and RBF doesn't exist in Dash - return state.Invalid(false, REJECT_CONFLICT, "txn-mempool-conflict"); + return state.Invalid(false, REJECT_DUPLICATE, "txn-mempool-conflict"); } } } @@ -741,7 +742,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool if (!had_coin_in_cache) { coins_to_uncache.push_back(outpoint); } - return state.Invalid(false, REJECT_ALREADY_KNOWN, "txn-already-known"); + return state.Invalid(false, REJECT_DUPLICATE, "txn-already-known"); } } diff --git a/src/validation.h b/src/validation.h index cd6c592247cd..db4da5a7ed66 100644 --- a/src/validation.h +++ b/src/validation.h @@ -522,10 +522,6 @@ bool GetBlockHash(uint256& hashRet, int nBlockHeight = -1); static const unsigned int REJECT_INTERNAL = 0x100; /** Too high fee. Can not be triggered by P2P transactions */ static const unsigned int REJECT_HIGHFEE = 0x100; -/** Transaction is already known (either in mempool or blockchain) */ -static const unsigned int REJECT_ALREADY_KNOWN = 0x101; -/** Transaction conflicts with a transaction already known */ -static const unsigned int REJECT_CONFLICT = 0x102; /** Get block file info entry for one block file */ CBlockFileInfo* GetBlockFileInfo(size_t n); From 82dcb03e353099d313269c74c81ce88c3e41751c Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 5 Jul 2019 12:34:38 -0500 Subject: [PATCH 390/987] REJECT_CONFLICT -> REJECT_DUPLICATE Signed-off-by: Pasta --- src/evo/deterministicmns.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 921905e1aaff..393219d06484 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -692,10 +692,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C } if (newList.HasUniqueProperty(proTx.addr)) { - return _state.DoS(100, false, REJECT_CONFLICT, "bad-protx-dup-addr"); + return _state.DoS(100, false, REJECT_DUPLICATE, "bad-protx-dup-addr"); } if (newList.HasUniqueProperty(proTx.keyIDOwner) || newList.HasUniqueProperty(proTx.pubKeyOperator)) { - return _state.DoS(100, false, REJECT_CONFLICT, "bad-protx-dup-key"); + return _state.DoS(100, false, REJECT_DUPLICATE, "bad-protx-dup-key"); } dmn->nOperatorReward = proTx.nOperatorReward; @@ -724,7 +724,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C } if (newList.HasUniqueProperty(proTx.addr) && newList.GetUniquePropertyMN(proTx.addr)->proTxHash != proTx.proTxHash) { - return _state.DoS(100, false, REJECT_CONFLICT, "bad-protx-dup-addr"); + return _state.DoS(100, false, REJECT_DUPLICATE, "bad-protx-dup-addr"); } CDeterministicMNCPtr dmn = newList.GetMN(proTx.proTxHash); From ed24dbba7b039029d1026048140c3a247aba92de Mon Sep 17 00:00:00 2001 From: Pasta Date: Fri, 5 Jul 2019 12:31:08 -0500 Subject: [PATCH 391/987] remove Boost_Reverse_foreach Signed-off-by: Pasta --- src/wallet/wallet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 748efbf6ad1c..9c613ff9fd05 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -5232,8 +5232,8 @@ bool AutoBackupWallet(CWallet* wallet, const std::string& strWalletFile_, std::s // Loop backward through backup files and keep the N newest ones (1 <= N <= 10) int counter = 0; - BOOST_REVERSE_FOREACH(std::pair file, folder_set) - { + for(auto it = folder_set.rbegin(); it != folder_set.rend(); ++it) { + std::pair file = *it; counter++; if (counter > nWalletBackups) { From 7802c82e3120cd3b21a1ad6dac49a7322aeed576 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 21 Jun 2017 14:26:10 +0200 Subject: [PATCH 392/987] Merge #10533: [tests] Use cookie auth instead of rpcuser and rpcpassword 279fde5 Check for rpcuser/rpcpassword first then for cookie (Andrew Chow) 3ec5ad8 Add test for rpcuser/rpcpassword (Andrew Chow) c53c983 Replace cookie auth in tests (Andrew Chow) Tree-SHA512: 21efb84c87080a895cac8a7fe4766738c34eebe9686c7d10af1bf91ed4ae422e2d5dbbebffd00d34744eb6bb2d0195ea3aca86deebf085bbdeeb1d8b474241ed --- test/functional/multi_rpc.py | 58 ++++++++++++++++--- test/functional/pruning.py | 4 +- test/functional/rpcbind_test.py | 2 +- .../test_framework/test_framework.py | 5 +- test/functional/test_framework/util.py | 48 ++++++++++----- 5 files changed, 92 insertions(+), 25 deletions(-) diff --git a/test/functional/multi_rpc.py b/test/functional/multi_rpc.py index 9e51810a8883..6870908b6591 100755 --- a/test/functional/multi_rpc.py +++ b/test/functional/multi_rpc.py @@ -16,16 +16,21 @@ class HTTPBasicsTest (BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = False - self.num_nodes = 1 + self.num_nodes = 2 def setup_chain(self): super().setup_chain() #Append rpcauth to dash.conf before initialization rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" + rpcuser = "rpcuser=rpcuser💻" + rpcpassword = "rpcpassword=rpcpassword🔑" with open(os.path.join(self.options.tmpdir+"/node0", "dash.conf"), 'a', encoding='utf8') as f: f.write(rpcauth+"\n") f.write(rpcauth2+"\n") + with open(os.path.join(self.options.tmpdir+"/node1", "bitcoin.conf"), 'a', encoding='utf8') as f: + f.write(rpcuser+"\n") + f.write(rpcpassword+"\n") def run_test(self): @@ -50,7 +55,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, False) + assert_equal(resp.status, 200) conn.close() #Use new authpair to confirm both work @@ -60,7 +65,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, False) + assert_equal(resp.status, 200) conn.close() #Wrong login name with rt's password @@ -71,7 +76,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, True) + assert_equal(resp.status, 401) conn.close() #Wrong password for rt @@ -82,7 +87,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, True) + assert_equal(resp.status, 401) conn.close() #Correct for rt2 @@ -93,7 +98,7 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, False) + assert_equal(resp.status, 200) conn.close() #Wrong password for rt2 @@ -104,7 +109,46 @@ def run_test(self): conn.connect() conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) resp = conn.getresponse() - assert_equal(resp.status==401, True) + assert_equal(resp.status, 401) + conn.close() + + ############################################################### + # Check correctness of the rpcuser/rpcpassword config options # + ############################################################### + url = urllib.parse.urlparse(self.nodes[1].url) + + # rpcuser and rpcpassword authpair + rpcuserauthpair = "rpcuser💻:rpcpassword🔑" + + headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)} + + conn = http.client.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status, 200) + conn.close() + + #Wrong login name with rpcuser's password + rpcuserauthpair = "rpcuserwrong:rpcpassword" + headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)} + + conn = http.client.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status, 401) + conn.close() + + #Wrong password for rpcuser + rpcuserauthpair = "rpcuser:rpcpasswordwrong" + headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)} + + conn = http.client.HTTPConnection(url.hostname, url.port) + conn.connect() + conn.request('POST', '/', '{"method": "getbestblockhash"}', headers) + resp = conn.getresponse() + assert_equal(resp.status, 401) conn.close() diff --git a/test/functional/pruning.py b/test/functional/pruning.py index 9ee09c1a72a3..501f98ad45bc 100755 --- a/test/functional/pruning.py +++ b/test/functional/pruning.py @@ -315,7 +315,7 @@ def wallet_test(self): # check that the pruning node's wallet is still in good shape self.log.info("Stop and start pruning node to trigger wallet rescan") self.stop_node(2) - self.start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) + self.nodes[2] = self.start_node(2, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) self.log.info("Success") # check that wallet loads loads successfully when restarting a pruned node after IBD. @@ -325,7 +325,7 @@ def wallet_test(self): nds = [self.nodes[0], self.nodes[5]] sync_blocks(nds, wait=5, timeout=300) self.stop_node(5) #stop and start to trigger rescan - self.start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) + self.nodes[5] = self.start_node(5, self.options.tmpdir, ["-litemode","-txindex=0","-prune=550"], stderr=sys.stdout) self.log.info("Success") def run_test(self): diff --git a/test/functional/rpcbind_test.py b/test/functional/rpcbind_test.py index 5336cf2ec89f..198599010e41 100755 --- a/test/functional/rpcbind_test.py +++ b/test/functional/rpcbind_test.py @@ -49,7 +49,7 @@ def run_allowip_test(self, allow_ips, rpchost, rpcport): base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir, [base_args]) # connect to node through non-loopback interface - node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0) + node = get_rpc_proxy(rpc_url(get_datadir_path(self.options.tmpdir, 0), 0, "%s:%d" % (rpchost, rpcport)), 0) node.getnetworkinfo() self.stop_nodes() diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index a663482eb392..273e9706f9e3 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -33,6 +33,7 @@ get_mocktime, get_rpc_proxy, initialize_datadir, + get_datadir_path, log_filename, p2p_port, rpc_url, @@ -319,13 +320,13 @@ def _initialize_chain(self, test_dir, num_nodes, cachedir, extra_args=None, stde args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr) self.log.debug("initialize_chain: dashd started, waiting for RPC to come up") - wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i) + wait_for_bitcoind_start(bitcoind_processes[i], datadir, i) self.log.debug("initialize_chain: RPC successfully started") self.nodes = [] for i in range(MAX_NODES): try: - self.nodes.append(get_rpc_proxy(rpc_url(i), i)) + self.nodes.append(get_rpc_proxy(rpc_url(get_datadir_path(cachedir, i), i), i)) except: self.log.exception("Error connecting to node %d" % i) sys.exit(1) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index f062e32da22f..825cc347edc5 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -205,21 +205,40 @@ def initialize_datadir(dirname, n): datadir = os.path.join(dirname, "node"+str(n)) if not os.path.isdir(datadir): os.makedirs(datadir) - rpc_u, rpc_p = rpc_auth_pair(n) with open(os.path.join(datadir, "dash.conf"), 'w', encoding='utf8') as f: f.write("regtest=1\n") - f.write("rpcuser=" + rpc_u + "\n") - f.write("rpcpassword=" + rpc_p + "\n") f.write("port="+str(p2p_port(n))+"\n") f.write("rpcport="+str(rpc_port(n))+"\n") f.write("listenonion=0\n") return datadir -def rpc_auth_pair(n): - return 'rpcuser💻' + str(n), 'rpcpass🔑' + str(n) - -def rpc_url(i, rpchost=None): - rpc_u, rpc_p = rpc_auth_pair(i) +def get_datadir_path(dirname, n): + return os.path.join(dirname, "node"+str(n)) + +def get_auth_cookie(datadir, n): + user = None + password = None + if os.path.isfile(os.path.join(datadir, "bitcoin.conf")): + with open(os.path.join(datadir, "bitcoin.conf"), 'r') as f: + for line in f: + if line.startswith("rpcuser="): + assert user is None # Ensure that there is only one rpcuser line + user = line.split("=")[1].strip("\n") + if line.startswith("rpcpassword="): + assert password is None # Ensure that there is only one rpcpassword line + password = line.split("=")[1].strip("\n") + if os.path.isfile(os.path.join(datadir, "regtest", ".cookie")): + with open(os.path.join(datadir, "regtest", ".cookie"), 'r') as f: + userpass = f.read() + split_userpass = userpass.split(':') + user = split_userpass[0] + password = split_userpass[1] + if user is None or password is None: + raise ValueError("No RPC credentials") + return user, password + +def rpc_url(datadir, i, rpchost=None): + rpc_u, rpc_p = get_auth_cookie(datadir, i) host = '127.0.0.1' port = rpc_port(i) if rpchost: @@ -230,7 +249,7 @@ def rpc_url(i, rpchost=None): host = rpchost return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port)) -def wait_for_bitcoind_start(process, url, i): +def wait_for_bitcoind_start(process, datadir, i, rpchost=None): ''' Wait for dashd to start. This means that RPC is accessible and fully initialized. Raise an exception if dashd exits during initialization. @@ -239,7 +258,8 @@ def wait_for_bitcoind_start(process, url, i): if process.poll() is not None: raise Exception('dashd exited with status %i during initialization' % process.returncode) try: - rpc = get_rpc_proxy(url, i) + # Check if .cookie file to be created + rpc = get_rpc_proxy(rpc_url(datadir, i, rpchost), i) blocks = rpc.getblockcount() break # break out of loop on success except IOError as e: @@ -248,6 +268,9 @@ def wait_for_bitcoind_start(process, url, i): except JSONRPCException as e: # Initialization phase if e.error['code'] != -28: # RPC in warmup? raise # unknown JSON RPC exception + except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting + if "No RPC credentials" not in str(e): + raise time.sleep(0.25) @@ -266,10 +289,9 @@ def _start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary bitcoind_processes[i] = subprocess.Popen(args, stderr=stderr) logger.debug("initialize_chain: dashd started, waiting for RPC to come up") - url = rpc_url(i, rpchost) - wait_for_bitcoind_start(bitcoind_processes[i], url, i) + wait_for_bitcoind_start(bitcoind_processes[i], datadir, i, rpchost) logger.debug("initialize_chain: RPC successfully started") - proxy = get_rpc_proxy(url, i, timeout=timewait) + proxy = get_rpc_proxy(rpc_url(datadir, i, rpchost), i, timeout=timewait) if COVERAGE_DIR: coverage.write_all_rpc_commands(COVERAGE_DIR, proxy) From eb1b61b364df5f3a6df5f134044605e23a8a3d88 Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 10 Jul 2019 09:42:53 -0500 Subject: [PATCH 393/987] fix indents Signed-off-by: Pasta --- src/util.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util.h b/src/util.h index 066614c3e47d..034f6205a1c9 100644 --- a/src/util.h +++ b/src/util.h @@ -298,8 +298,8 @@ class ArgsManager // Forces an arg setting. Called by SoftSetArg() if the arg hasn't already // been set. Also called directly in testing. void ForceSetArg(const std::string& strArg, const std::string& strValue); -void ForceSetMultiArgs(const std::string& strArg, const std::vector& values); -void ForceRemoveArg(const std::string& strArg); + void ForceSetMultiArgs(const std::string& strArg, const std::vector& values); + void ForceRemoveArg(const std::string& strArg); }; extern ArgsManager gArgs; From 722c373f517fce680adfa2951e4359cc64de40f0 Mon Sep 17 00:00:00 2001 From: Pasta Date: Wed, 10 Jul 2019 09:45:09 -0500 Subject: [PATCH 394/987] bitcoin -> dash Signed-off-by: Pasta --- test/functional/multi_rpc.py | 2 +- test/functional/test_framework/util.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/functional/multi_rpc.py b/test/functional/multi_rpc.py index 6870908b6591..891184ca6e82 100755 --- a/test/functional/multi_rpc.py +++ b/test/functional/multi_rpc.py @@ -28,7 +28,7 @@ def setup_chain(self): with open(os.path.join(self.options.tmpdir+"/node0", "dash.conf"), 'a', encoding='utf8') as f: f.write(rpcauth+"\n") f.write(rpcauth2+"\n") - with open(os.path.join(self.options.tmpdir+"/node1", "bitcoin.conf"), 'a', encoding='utf8') as f: + with open(os.path.join(self.options.tmpdir+"/node1", "dash.conf"), 'a', encoding='utf8') as f: f.write(rpcuser+"\n") f.write(rpcpassword+"\n") diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index 825cc347edc5..c5a87cbd55c8 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -218,8 +218,8 @@ def get_datadir_path(dirname, n): def get_auth_cookie(datadir, n): user = None password = None - if os.path.isfile(os.path.join(datadir, "bitcoin.conf")): - with open(os.path.join(datadir, "bitcoin.conf"), 'r') as f: + if os.path.isfile(os.path.join(datadir, "dash.conf")): + with open(os.path.join(datadir, "dash.conf"), 'r') as f: for line in f: if line.startswith("rpcuser="): assert user is None # Ensure that there is only one rpcuser line @@ -268,7 +268,7 @@ def wait_for_bitcoind_start(process, datadir, i, rpchost=None): except JSONRPCException as e: # Initialization phase if e.error['code'] != -28: # RPC in warmup? raise # unknown JSON RPC exception - except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting + except ValueError as e: # cookie file not found and no rpcuser or rpcassword. dashd still starting if "No RPC credentials" not in str(e): raise time.sleep(0.25) From 6489e678ce097a8f8f91f661fa6836dbc795406f Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Fri, 7 Jul 2017 13:28:44 +0200 Subject: [PATCH 395/987] Merge #10759: Fix multi_rpc test for hosts that dont default to utf8 bc7d103 Fix multi_rpc test for hosts that dont default to utf8 (Matt Corallo) Tree-SHA512: 7644b1f50d4010a08aed5d1c87ab7326af9c109ac05dfbfc4bb6d5a19ace7997ef9cdd64d4301072f1106225de6d3aacccb17f53043b55ba61f5723c2b65af30 --- test/functional/test_framework/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index c5a87cbd55c8..f6c326ac8fd7 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -219,7 +219,7 @@ def get_auth_cookie(datadir, n): user = None password = None if os.path.isfile(os.path.join(datadir, "dash.conf")): - with open(os.path.join(datadir, "dash.conf"), 'r') as f: + with open(os.path.join(datadir, "dash.conf"), 'r', encoding='utf8') as f: for line in f: if line.startswith("rpcuser="): assert user is None # Ensure that there is only one rpcuser line From 2cbf726ab04d5e7b0009a29331e9d14072bd3e82 Mon Sep 17 00:00:00 2001 From: PastaPastaPasta Date: Thu, 11 Jul 2019 02:50:52 -0500 Subject: [PATCH 396/987] Backport #8694: Basic multiwallet support (#3022) * Merge #8694: Basic multiwallet support c237bd7 wallet: Update formatting (Luke Dashjr) 9cbe8c8 wallet: Forbid -salvagewallet, -zapwallettxes, and -upgradewallet with multiple wallets (Luke Dashjr) a2a5f3f wallet: Base backup filenames on original wallet filename (Luke Dashjr) b823a4c wallet: Include actual backup filename in recovery warning message (Luke Dashjr) 84dcb45 Bugfix: wallet: Fix warningStr, errorStr argument order (Luke Dashjr) 008c360 Wallet: Move multiwallet sanity checks to CWallet::Verify, and do other checks on all wallets (Luke Dashjr) 0f08575 Wallet: Support loading multiple wallets if -wallet used more than once (Luke Dashjr) b124cf0 Wallet: Replace pwalletMain with a vector of wallet pointers (Luke Dashjr) 19b3648 CWalletDB: Store the update counter per wallet (Luke Dashjr) 74e8738 Bugfix: ForceSetArg should replace entr(ies) in mapMultiArgs, not append (Luke Dashjr) 23fb9ad wallet: Move nAccountingEntryNumber from static/global to CWallet (Luke Dashjr) 9d15d55 Bugfix: wallet: Increment "update counter" when modifying account stuff (Luke Dashjr) f28eb80 Bugfix: wallet: Increment "update counter" only after actually making the applicable db changes to avoid potential races (Luke Dashjr) Tree-SHA512: 23f5dda58477307bc07997010740f1dc729164cdddefd2f9a2c9c7a877111eb1516d3e2ad4f9b104621f0b7f17369c69fcef13d28b85cb6c01d35f09a8845f23 * pwalletMain -> vpwallets Signed-off-by: Pasta * add gArgs Signed-off-by: Pasta * continued pwalletsMain -> vpwallets Signed-off-by: Pasta * remove external pwalletMains and pwalletMain -> vpwallet Signed-off-by: Pasta * add external referance to vpwallets Signed-off-by: Pasta * more pWalletMain -> vpwallets[0] Signed-off-by: Pasta * code review Signed-off-by: Pasta * revert LOCK(cs_main) move Signed-off-by: Pasta * import wallet.h and remove extern Signed-off-by: Pasta * batch.* -> WriteIC and EraseIC Signed-off-by: Pasta * wrap wallet.h include inside of an ifdef Signed-off-by: Pasta * drop wallet.h Signed-off-by: Pasta * add dropped "!" Signed-off-by: Pasta --- src/init.cpp | 29 +++-- src/privatesend/privatesend-client.cpp | 106 ++++++++-------- src/qt/coincontroldialog.cpp | 4 +- src/qt/dash.cpp | 5 +- src/qt/optionsdialog.cpp | 9 +- src/qt/overviewpage.cpp | 20 +-- src/util.cpp | 1 + src/wallet/db.cpp | 22 ++-- src/wallet/db.h | 20 ++- src/wallet/rpcwallet.cpp | 3 +- src/wallet/test/wallet_test_fixture.cpp | 2 + src/wallet/test/wallet_tests.cpp | 14 +-- src/wallet/wallet.cpp | 89 +++++++------ src/wallet/wallet.h | 5 +- src/wallet/walletdb.cpp | 160 +++++++++--------------- src/wallet/walletdb.h | 33 +++-- 16 files changed, 275 insertions(+), 247 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 242be406398f..dfc9811e7b47 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -246,8 +246,9 @@ void PrepareShutdown() privateSendClient.fPrivateSendRunning = false; privateSendClient.ResetPool(); } - if (pwalletMain) - pwalletMain->Flush(false); + for (CWalletRef pwallet : vpwallets) { + pwallet->Flush(false); + } #endif MapPort(false); UnregisterValidationInterface(peerLogic.get()); @@ -306,8 +307,9 @@ void PrepareShutdown() evoDb = NULL; } #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->Flush(true); + for (CWalletRef pwallet : vpwallets) { + pwallet->Flush(true); + } #endif #if ENABLE_ZMQ @@ -359,8 +361,10 @@ void Shutdown() // Shutdown part 2: Stop TOR thread and delete wallet instance StopTorControl(); #ifdef ENABLE_WALLET - delete pwalletMain; - pwalletMain = NULL; + for (CWalletRef pwallet : vpwallets) { + delete pwallet; + } + vpwallets.clear(); #endif globalVerifyHandle.reset(); ECC_Stop(); @@ -834,8 +838,8 @@ void ThreadImport(std::vector vImportFiles) #ifdef ENABLE_WALLET // we can't do this before DIP3 is fully initialized - if (pwalletMain) { - pwalletMain->AutoLockMasternodeCollaterals(); + for (CWalletRef pwallet : vpwallets) { + pwallet->AutoLockMasternodeCollaterals(); } #endif @@ -1998,11 +2002,11 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) nMaxRounds = std::numeric_limits::max(); } - if (pwalletMain == nullptr) { + if (vpwallets.empty()) { privateSendClient.fEnablePrivateSend = privateSendClient.fPrivateSendRunning = false; } else { privateSendClient.fEnablePrivateSend = gArgs.GetBoolArg("-enableprivatesend", !fLiteMode); - privateSendClient.fPrivateSendRunning = pwalletMain->IsLocked() ? false : gArgs.GetBoolArg("-privatesendautostart", DEFAULT_PRIVATESEND_AUTOSTART); + privateSendClient.fPrivateSendRunning = vpwallets[0]->IsLocked() ? false : gArgs.GetBoolArg("-privatesendautostart", DEFAULT_PRIVATESEND_AUTOSTART); } privateSendClient.fPrivateSendMultiSession = gArgs.GetBoolArg("-privatesendmultisession", DEFAULT_PRIVATESEND_MULTISESSION); privateSendClient.nPrivateSendSessions = std::min(std::max((int)gArgs.GetArg("-privatesendsessions", DEFAULT_PRIVATESEND_SESSIONS), MIN_PRIVATESEND_SESSIONS), MAX_PRIVATESEND_SESSIONS); @@ -2151,8 +2155,9 @@ bool AppInitMain(boost::thread_group& threadGroup, CScheduler& scheduler) uiInterface.InitMessage(_("Done loading")); #ifdef ENABLE_WALLET - if (pwalletMain) - pwalletMain->postInitProcess(scheduler); + for (CWalletRef pwallet : vpwallets) { + pwallet->postInitProcess(scheduler); + } #endif return true; diff --git a/src/privatesend/privatesend-client.cpp b/src/privatesend/privatesend-client.cpp index 2e6a08ddc855..7cf50df5877a 100644 --- a/src/privatesend/privatesend-client.cpp +++ b/src/privatesend/privatesend-client.cpp @@ -268,13 +268,13 @@ void CPrivateSendClientSession::UnlockCoins() if (!privateSendClient.fEnablePrivateSend) return; while (true) { - TRY_LOCK(pwalletMain->cs_wallet, lockWallet); + TRY_LOCK(vpwallets[0]->cs_wallet, lockWallet); if (!lockWallet) { MilliSleep(50); continue; } for (const auto& outpoint : vecOutPointLocked) - pwalletMain->UnlockCoin(outpoint); + vpwallets[0]->UnlockCoin(outpoint); break; } @@ -616,7 +616,7 @@ bool CPrivateSendClientSession::SignFinalTransaction(const CTransaction& finalTr return false; } - const CKeyStore& keystore = *pwalletMain; + const CKeyStore& keystore = *vpwallets[0]; LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::SignFinalTransaction -- Signing my input %i\n", nMyInputIndex); if (!SignSignature(keystore, prevPubKey, finalMutableTransaction, nMyInputIndex, int(SIGHASH_ALL | SIGHASH_ANYONECANPAY))) { // changes scriptSig @@ -706,7 +706,7 @@ bool CPrivateSendClientManager::CheckAutomaticBackup() LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Automatic backups disabled, no mixing available.\n"); strAutoDenomResult = _("Automatic backups disabled") + ", " + _("no mixing available."); fPrivateSendRunning = false; // stop mixing - pwalletMain->nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup" + vpwallets[0]->nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup" return false; case -1: // Automatic backup failed, nothing else we can do until user fixes the issue manually. @@ -724,24 +724,24 @@ bool CPrivateSendClientManager::CheckAutomaticBackup() return false; } - if (pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_STOP) { + if (vpwallets[0]->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_STOP) { // We should never get here via mixing itself but probably smth else is still actively using keypool - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d, no mixing available.\n", pwalletMain->nKeysLeftSinceAutoBackup); - strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + ", " + _("no mixing available."), pwalletMain->nKeysLeftSinceAutoBackup); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d, no mixing available.\n", vpwallets[0]->nKeysLeftSinceAutoBackup); + strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + ", " + _("no mixing available."), vpwallets[0]->nKeysLeftSinceAutoBackup); // It's getting really dangerous, stop mixing fPrivateSendRunning = false; return false; - } else if (pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { + } else if (vpwallets[0]->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { // Low number of keys left but it's still more or less safe to continue - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d\n", pwalletMain->nKeysLeftSinceAutoBackup); - strAutoDenomResult = strprintf(_("Very low number of keys left: %d"), pwalletMain->nKeysLeftSinceAutoBackup); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Very low number of keys left: %d\n", vpwallets[0]->nKeysLeftSinceAutoBackup); + strAutoDenomResult = strprintf(_("Very low number of keys left: %d"), vpwallets[0]->nKeysLeftSinceAutoBackup); if (fCreateAutoBackups) { LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Trying to create new backup.\n"); std::string warningString; std::string errorString; - if (!AutoBackupWallet(pwalletMain, "", warningString, errorString)) { + if (!AutoBackupWallet(vpwallets[0], "", warningString, errorString)) { if (!warningString.empty()) { // There were some issues saving backup but yet more or less safe to continue LogPrintf("CPrivateSendClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", warningString); @@ -759,7 +759,7 @@ bool CPrivateSendClientManager::CheckAutomaticBackup() } } - LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Keys left since latest backup: %d\n", pwalletMain->nKeysLeftSinceAutoBackup); + LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientManager::CheckAutomaticBackup -- Keys left since latest backup: %d\n", vpwallets[0]->nKeysLeftSinceAutoBackup); return true; } @@ -782,9 +782,9 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool CAmount nBalanceNeedsAnonymized; { - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, vpwallets[0]->cs_wallet); - if (!fDryRun && pwalletMain->IsLocked(true)) { + if (!fDryRun && vpwallets[0]->IsLocked(true)) { strAutoDenomResult = _("Wallet is locked."); return false; } @@ -807,7 +807,7 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool } // check if there is anything left to do - CAmount nBalanceAnonymized = pwalletMain->GetAnonymizedBalance(); + CAmount nBalanceAnonymized = vpwallets[0]->GetAnonymizedBalance(); nBalanceNeedsAnonymized = privateSendClient.nPrivateSendAmount*COIN - nBalanceAnonymized; if (nBalanceNeedsAnonymized < 0) { @@ -819,13 +819,13 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool CAmount nValueMin = CPrivateSend::GetSmallestDenomination(); // if there are no confirmed DS collateral inputs yet - if (!pwalletMain->HasCollateralInputs()) { + if (!vpwallets[0]->HasCollateralInputs()) { // should have some additional amount for them nValueMin += CPrivateSend::GetMaxCollateralAmount(); } // including denoms but applying some restrictions - CAmount nBalanceAnonymizable = pwalletMain->GetAnonymizableBalance(); + CAmount nBalanceAnonymizable = vpwallets[0]->GetAnonymizableBalance(); // anonymizable balance is way too small if (nBalanceAnonymizable < nValueMin) { @@ -835,10 +835,10 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool } // excluding denoms - CAmount nBalanceAnonimizableNonDenom = pwalletMain->GetAnonymizableBalance(true); + CAmount nBalanceAnonimizableNonDenom = vpwallets[0]->GetAnonymizableBalance(true); // denoms - CAmount nBalanceDenominatedConf = pwalletMain->GetDenominatedBalance(); - CAmount nBalanceDenominatedUnconf = pwalletMain->GetDenominatedBalance(true); + CAmount nBalanceDenominatedConf = vpwallets[0]->GetDenominatedBalance(); + CAmount nBalanceDenominatedUnconf = vpwallets[0]->GetDenominatedBalance(true); CAmount nBalanceDenominated = nBalanceDenominatedConf + nBalanceDenominatedUnconf; CAmount nBalanceToDenominate = privateSendClient.nPrivateSendAmount * COIN - nBalanceDenominated; @@ -887,8 +887,8 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool } //check if we have the collateral sized inputs - if (!pwalletMain->HasCollateralInputs()) { - return !pwalletMain->HasCollateralInputs(false) && MakeCollateralAmounts(connman); + if (!vpwallets[0]->HasCollateralInputs()) { + return !vpwallets[0]->HasCollateralInputs(false) && MakeCollateralAmounts(connman); } if (nSessionID) { @@ -912,20 +912,20 @@ bool CPrivateSendClientSession::DoAutomaticDenominating(CConnman& connman, bool //check our collateral and create new if needed std::string strReason; if (txMyCollateral == CMutableTransaction()) { - if (!pwalletMain->CreateCollateralTransaction(txMyCollateral, strReason)) { + if (!vpwallets[0]->CreateCollateralTransaction(txMyCollateral, strReason)) { LogPrintf("CPrivateSendClientSession::DoAutomaticDenominating -- create collateral error:%s\n", strReason); return false; } } else { if (!CPrivateSend::IsCollateralValid(txMyCollateral)) { LogPrintf("CPrivateSendClientSession::DoAutomaticDenominating -- invalid collateral, recreating...\n"); - if (!pwalletMain->CreateCollateralTransaction(txMyCollateral, strReason)) { + if (!vpwallets[0]->CreateCollateralTransaction(txMyCollateral, strReason)) { LogPrintf("CPrivateSendClientSession::DoAutomaticDenominating -- create collateral error: %s\n", strReason); return false; } } } - } // LOCK2(cs_main, pwalletMain->cs_wallet); + } // LOCK2(cs_main, vpwallets[0]->cs_wallet); bool fUseQueue = GetRandInt(100) > 33; // don't use the queues all of the time for mixing unless we are a liquidity provider @@ -952,7 +952,7 @@ bool CPrivateSendClientManager::DoAutomaticDenominating(CConnman& connman, bool return false; } - if (!fDryRun && pwalletMain->IsLocked(true)) { + if (!fDryRun && vpwallets[0]->IsLocked(true)) { strAutoDenomResult = _("Wallet is locked."); return false; } @@ -1073,7 +1073,7 @@ bool CPrivateSendClientSession::JoinExistingQueue(CAmount nBalanceNeedsAnonymize CAmount nMaxAmount = nBalanceNeedsAnonymized; // Try to match their denominations if possible, select exact number of denominations - if (!pwalletMain->SelectPSInOutPairsByDenominations(dsq.nDenom, nMinAmount, nMaxAmount, vecPSInOutPairsTmp)) { + if (!vpwallets[0]->SelectPSInOutPairsByDenominations(dsq.nDenom, nMinAmount, nMaxAmount, vecPSInOutPairsTmp)) { LogPrintf("CPrivateSendClientSession::JoinExistingQueue -- Couldn't match %d denominations %d (%s)\n", vecBits.front(), dsq.nDenom, CPrivateSend::GetDenominationsToString(dsq.nDenom)); continue; } @@ -1112,7 +1112,7 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, C // ** find the coins we'll use std::vector vecTxIn; CAmount nValueInTmp = 0; - if (!pwalletMain->SelectPrivateCoins(CPrivateSend::GetSmallestDenomination(), nBalanceNeedsAnonymized, vecTxIn, nValueInTmp, 0, privateSendClient.nPrivateSendRounds - 1)) { + if (!vpwallets[0]->SelectPrivateCoins(CPrivateSend::GetSmallestDenomination(), nBalanceNeedsAnonymized, vecTxIn, nValueInTmp, 0, privateSendClient.nPrivateSendRounds - 1)) { // this should never happen LogPrintf("CPrivateSendClientSession::StartNewQueue -- Can't mix: no compatible inputs found!\n"); strAutoDenomResult = _("Can't mix: no compatible inputs found!"); @@ -1157,7 +1157,7 @@ bool CPrivateSendClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, C LogPrintf("CPrivateSendClientSession::StartNewQueue -- attempt %d connection to Masternode %s\n", nTries, dmn->pdmnState->addr.ToString()); std::vector vecAmounts; - pwalletMain->ConvertList(vecTxIn, vecAmounts); + vpwallets[0]->ConvertList(vecTxIn, vecAmounts); // try to get a single random denom out of vecAmounts while (nSessionDenom == 0) { nSessionDenom = CPrivateSend::GetDenominationsByAmounts(vecAmounts); @@ -1214,7 +1214,7 @@ void CPrivateSendClientManager::ProcessPendingDsaRequest(CConnman& connman) bool CPrivateSendClientSession::SubmitDenominate(CConnman& connman) { - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, vpwallets[0]->cs_wallet); std::string strError; std::vector > vecPSInOutPairs, vecPSInOutPairsTmp; @@ -1272,7 +1272,7 @@ bool CPrivateSendClientSession::SelectDenominate(std::string& strErrorRet, std:: { if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; - if (pwalletMain->IsLocked(true)) { + if (vpwallets[0]->IsLocked(true)) { strErrorRet = "Wallet locked, unable to create transaction!"; return false; } @@ -1291,7 +1291,7 @@ bool CPrivateSendClientSession::SelectDenominate(std::string& strErrorRet, std:: } std::vector vecStandardDenoms = CPrivateSend::GetStandardDenominations(); - bool fSelected = pwalletMain->SelectPSInOutPairsByDenominations(nSessionDenom, vecStandardDenoms[vecBits.front()], CPrivateSend::GetMaxPoolAmount(), vecPSInOutPairsRet); + bool fSelected = vpwallets[0]->SelectPSInOutPairsByDenominations(nSessionDenom, vecStandardDenoms[vecBits.front()], CPrivateSend::GetMaxPoolAmount(), vecPSInOutPairsRet); if (!fSelected) { strErrorRet = "Can't select current denominated inputs"; return false; @@ -1309,7 +1309,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds } for (const auto& pair : vecPSInOutPairsIn) { - pwalletMain->LockCoin(pair.first.prevout); + vpwallets[0]->LockCoin(pair.first.prevout); } // NOTE: No need to randomize order of inputs because they were @@ -1324,7 +1324,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds for (const auto& pair : vecPSInOutPairsIn) { if (pair.second.nRounds < nMinRounds || pair.second.nRounds > nMaxRounds) { // unlock unused coins - pwalletMain->UnlockCoin(pair.first.prevout); + vpwallets[0]->UnlockCoin(pair.first.prevout); continue; } bool fFound = false; @@ -1344,7 +1344,7 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds ++vecSteps[nBit]; break; } - scriptDenom = keyHolderStorage.AddKey(pwalletMain); + scriptDenom = keyHolderStorage.AddKey(vpwallets[0]); } vecPSInOutPairsRet.emplace_back(pair.first, CTxOut(nValueDenom, scriptDenom)); fFound = true; @@ -1356,14 +1356,14 @@ bool CPrivateSendClientSession::PrepareDenominate(int nMinRounds, int nMaxRounds } if (!fFound || fDryRun) { // unlock unused coins and if we are not going to mix right away - pwalletMain->UnlockCoin(pair.first.prevout); + vpwallets[0]->UnlockCoin(pair.first.prevout); } } if (nDenomResult != nSessionDenom) { // unlock used coins on failure for (const auto& pair : vecPSInOutPairsRet) { - pwalletMain->UnlockCoin(pair.first.prevout); + vpwallets[0]->UnlockCoin(pair.first.prevout); } keyHolderStorage.ReturnAll(); strErrorRet = "Can't prepare current denominated outputs"; @@ -1379,7 +1379,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(CConnman& connman) if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; std::vector vecTally; - if (!pwalletMain->SelectCoinsGroupedByAddresses(vecTally, false, false)) { + if (!vpwallets[0]->SelectCoinsGroupedByAddresses(vecTally, false, false)) { LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::MakeCollateralAmounts -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); return false; } @@ -1411,7 +1411,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta { if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, vpwallets[0]->cs_wallet); // denominated input is always a single one, so we can check its amount directly and return early if (!fTryDenominated && tallyItem.vecOutPoints.size() == 1 && CPrivateSend::IsDenominatedAmount(tallyItem.nAmount)) { @@ -1425,9 +1425,9 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta std::vector vecSend; // make our collateral address - CReserveKey reservekeyCollateral(pwalletMain); + CReserveKey reservekeyCollateral(vpwallets[0]); // make our change address - CReserveKey reservekeyChange(pwalletMain); + CReserveKey reservekeyChange(vpwallets[0]); CScript scriptCollateral; CPubKey vchPubKey; @@ -1446,14 +1446,14 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta coinControl.Select(outpoint); } - bool fSuccess = pwalletMain->CreateTransaction(vecSend, wtx, reservekeyChange, + bool fSuccess = vpwallets[0]->CreateTransaction(vecSend, wtx, reservekeyChange, nFeeRet, nChangePosRet, strFail, &coinControl, true, ONLY_NONDENOMINATED); if (!fSuccess) { LogPrintf("CPrivateSendClientSession::MakeCollateralAmounts -- ONLY_NONDENOMINATED: %s\n", strFail); // If we failed then most likely there are not enough funds on this address. if (fTryDenominated) { // Try to also use denominated coins (we can't mix denominated without collaterals anyway). - if (!pwalletMain->CreateTransaction(vecSend, wtx, reservekeyChange, + if (!vpwallets[0]->CreateTransaction(vecSend, wtx, reservekeyChange, nFeeRet, nChangePosRet, strFail, &coinControl, true, ALL_COINS)) { LogPrintf("CPrivateSendClientSession::MakeCollateralAmounts -- ALL_COINS Error: %s\n", strFail); reservekeyCollateral.ReturnKey(); @@ -1472,7 +1472,7 @@ bool CPrivateSendClientSession::MakeCollateralAmounts(const CompactTallyItem& ta // use the same nCachedLastSuccessBlock as for DS mixing to prevent race CValidationState state; - if (!pwalletMain->CommitTransaction(wtx, reservekeyChange, &connman, state)) { + if (!vpwallets[0]->CommitTransaction(wtx, reservekeyChange, &connman, state)) { LogPrintf("CPrivateSendClientSession::MakeCollateralAmounts -- CommitTransaction failed! Reason given: %s\n", state.GetRejectReason()); return false; } @@ -1487,14 +1487,14 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, { if (!privateSendClient.fEnablePrivateSend || !privateSendClient.fPrivateSendRunning) return false; - LOCK2(cs_main, pwalletMain->cs_wallet); + LOCK2(cs_main, vpwallets[0]->cs_wallet); // NOTE: We do not allow txes larger than 100kB, so we have to limit number of inputs here. // We still want to consume a lot of inputs to avoid creating only smaller denoms though. // Knowing that each CTxIn is at least 148b big, 400 inputs should take 400 x ~148b = ~60kB. // This still leaves more than enough room for another data of typical CreateDenominated tx. std::vector vecTally; - if (!pwalletMain->SelectCoinsGroupedByAddresses(vecTally, true, true, true, 400)) { + if (!vpwallets[0]->SelectCoinsGroupedByAddresses(vecTally, true, true, true, 400)) { LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- SelectCoinsGroupedByAddresses can't find any inputs!\n"); return false; } @@ -1504,7 +1504,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, return a.nAmount > b.nAmount; }); - bool fCreateMixingCollaterals = !pwalletMain->HasCollateralInputs(); + bool fCreateMixingCollaterals = !vpwallets[0]->HasCollateralInputs(); for (const auto& item : vecTally) { if (!CreateDenominated(nBalanceToDenominate, item, fCreateMixingCollaterals, connman)) continue; @@ -1531,7 +1531,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // ****** Add an output for mixing collaterals ************ / if (fCreateMixingCollaterals) { - CScript scriptCollateral = keyHolderStorageDenom.AddKey(pwalletMain); + CScript scriptCollateral = keyHolderStorageDenom.AddKey(vpwallets[0]); vecSend.push_back((CRecipient){scriptCollateral, CPrivateSend::GetMaxCollateralAmount(), false}); nValueLeft -= CPrivateSend::GetMaxCollateralAmount(); } @@ -1556,7 +1556,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, } // find new denoms to skip if any (ignore the largest one) - if (nDenomValue != vecStandardDenoms.front() && pwalletMain->CountInputsWithAmount(nDenomValue) > privateSendClient.nPrivateSendDenoms) { + if (nDenomValue != vecStandardDenoms.front() && vpwallets[0]->CountInputsWithAmount(nDenomValue) > privateSendClient.nPrivateSendDenoms) { strAutoDenomResult = strprintf(_("Too many %f denominations, removing."), (float)nDenomValue / COIN); LogPrint(BCLog::PRIVATESEND, "CPrivateSendClientSession::CreateDenominated -- %s\n", strAutoDenomResult); privateSendClient.AddSkippedDenom(nDenomValue); @@ -1577,7 +1577,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, // add each output up to 11 times until it can't be added again while (needMoreOutputs() && nOutputs <= 10) { - CScript scriptDenom = keyHolderStorageDenom.AddKey(pwalletMain); + CScript scriptDenom = keyHolderStorageDenom.AddKey(vpwallets[0]); vecSend.push_back((CRecipient){scriptDenom, nDenomValue, false}); @@ -1612,9 +1612,9 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, int nChangePosRet = -1; std::string strFail = ""; // make our change address - CReserveKey reservekeyChange(pwalletMain); + CReserveKey reservekeyChange(vpwallets[0]); - bool fSuccess = pwalletMain->CreateTransaction(vecSend, wtx, reservekeyChange, + bool fSuccess = vpwallets[0]->CreateTransaction(vecSend, wtx, reservekeyChange, nFeeRet, nChangePosRet, strFail, &coinControl, true, ONLY_NONDENOMINATED); if (!fSuccess) { LogPrintf("CPrivateSendClientSession::CreateDenominated -- Error: %s\n", strFail); @@ -1625,7 +1625,7 @@ bool CPrivateSendClientSession::CreateDenominated(CAmount nBalanceToDenominate, keyHolderStorageDenom.KeepAll(); CValidationState state; - if (!pwalletMain->CommitTransaction(wtx, reservekeyChange, &connman, state)) { + if (!vpwallets[0]->CommitTransaction(wtx, reservekeyChange, &connman, state)) { LogPrintf("CPrivateSendClientSession::CreateDenominated -- CommitTransaction failed! Reason given: %s\n", state.GetRejectReason()); return false; } diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index f6c47e025fdc..8c7f9430199f 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -431,7 +431,7 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); else { coinControl->Select(outpt); - int nRounds = pwalletMain->GetRealOutpointPrivateSendRounds(outpt); + int nRounds = vpwallets[0]->GetRealOutpointPrivateSendRounds(outpt); if (coinControl->fUsePrivateSend && nRounds < privateSendClient.nPrivateSendRounds) { QMessageBox::warning(this, windowTitle(), tr("Non-anonymized input selected. PrivateSend will be disabled.

    If you still want to use PrivateSend, please deselect all non-anonymized inputs first and then check the PrivateSend checkbox again."), @@ -751,7 +751,7 @@ void CoinControlDialog::updateView() // PrivateSend rounds COutPoint outpoint = COutPoint(out.tx->tx->GetHash(), out.i); - int nRounds = pwalletMain->GetRealOutpointPrivateSendRounds(outpoint); + int nRounds = vpwallets[0]->GetRealOutpointPrivateSendRounds(outpoint); if (nRounds >= 0 || LogAcceptCategory(BCLog::PRIVATESEND)) itemOutput->setText(COLUMN_PRIVATESEND_ROUNDS, QString::number(nRounds)); else itemOutput->setText(COLUMN_PRIVATESEND_ROUNDS, tr("n/a")); diff --git a/src/qt/dash.cpp b/src/qt/dash.cpp index c4353b301b5c..b538367fb7c3 100644 --- a/src/qt/dash.cpp +++ b/src/qt/dash.cpp @@ -507,9 +507,10 @@ void BitcoinApplication::initializeResult(bool success) window->setClientModel(clientModel); #ifdef ENABLE_WALLET - if(pwalletMain) + // TODO: Expose secondary wallets + if (!vpwallets.empty()) { - walletModel = new WalletModel(platformStyle, pwalletMain, optionsModel); + walletModel = new WalletModel(platformStyle, vpwallets[0], optionsModel); window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel); window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET); diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index da3789742064..cfb70c41b2df 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -31,8 +31,9 @@ #include #ifdef ENABLE_WALLET -extern CWallet* pwalletMain; -#endif // ENABLE_WALLET +typedef CWallet* CWalletRef; +extern std::vector vpwallets; +#endif //ENABLE_WALLET OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) : QDialog(parent), @@ -272,8 +273,8 @@ void OptionsDialog::on_okButton_clicked() mapper->submit(); #ifdef ENABLE_WALLET privateSendClient.nCachedNumBlocks = std::numeric_limits::max(); - if(pwalletMain) - pwalletMain->MarkDirty(); + if(!vpwallets.empty()) + vpwallets[0]->MarkDirty(); #endif // ENABLE_WALLET accept(); updateDefaultProxyNets(); diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 95c70218fb3e..cb79034e7dc9 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -341,7 +341,7 @@ void OverviewPage::updatePrivateSendProgress() { if(!masternodeSync.IsBlockchainSynced() || ShutdownRequested()) return; - if(!pwalletMain) return; + if(vpwallets.empty()) return; QString strAmountAndRounds; QString strPrivateSendAmount = BitcoinUnits::formatHtmlWithUnit(nDisplayUnit, privateSendClient.nPrivateSendAmount * COIN, false, BitcoinUnits::separatorAlways); @@ -360,7 +360,7 @@ void OverviewPage::updatePrivateSendProgress() return; } - CAmount nAnonymizableBalance = pwalletMain->GetAnonymizableBalance(false, false); + CAmount nAnonymizableBalance = vpwallets[0]->GetAnonymizableBalance(false, false); CAmount nMaxToAnonymize = nAnonymizableBalance + currentAnonymizedBalance; @@ -394,10 +394,10 @@ void OverviewPage::updatePrivateSendProgress() CAmount nNormalizedAnonymizedBalance; float nAverageAnonymizedRounds; - nDenominatedConfirmedBalance = pwalletMain->GetDenominatedBalance(); - nDenominatedUnconfirmedBalance = pwalletMain->GetDenominatedBalance(true); - nNormalizedAnonymizedBalance = pwalletMain->GetNormalizedAnonymizedBalance(); - nAverageAnonymizedRounds = pwalletMain->GetAverageAnonymizedRounds(); + nDenominatedConfirmedBalance = vpwallets[0]->GetDenominatedBalance(); + nDenominatedUnconfirmedBalance = vpwallets[0]->GetDenominatedBalance(true); + nNormalizedAnonymizedBalance = vpwallets[0]->GetNormalizedAnonymizedBalance(); + nAverageAnonymizedRounds = vpwallets[0]->GetAverageAnonymizedRounds(); // calculate parts of the progress, each of them shouldn't be higher than 1 // progress of denominating @@ -473,8 +473,8 @@ void OverviewPage::privateSendStatus() if(((nBestHeight - privateSendClient.nCachedNumBlocks) / (GetTimeMillis() - nLastDSProgressBlockTime + 1) > 1)) return; nLastDSProgressBlockTime = GetTimeMillis(); - QString strKeysLeftText(tr("keys left: %1").arg(pwalletMain->nKeysLeftSinceAutoBackup)); - if(pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { + QString strKeysLeftText(tr("keys left: %1").arg(vpwallets[0]->nKeysLeftSinceAutoBackup)); + if(vpwallets[0]->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { strKeysLeftText = "" + strKeysLeftText + ""; } ui->labelPrivateSendEnabled->setToolTip(strKeysLeftText); @@ -498,7 +498,7 @@ void OverviewPage::privateSendStatus() // Warn user that wallet is running out of keys // NOTE: we do NOT warn user and do NOT create autobackups if mixing is not running - if (nWalletBackups > 0 && pwalletMain->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { + if (nWalletBackups > 0 && vpwallets[0]->nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING) { QSettings settings; if(settings.value("fLowKeysWarning").toBool()) { QString strWarn = tr("Very low number of keys left since last automatic backup!") + "

    " + @@ -515,7 +515,7 @@ void OverviewPage::privateSendStatus() std::string strBackupWarning; std::string strBackupError; - if(!AutoBackupWallet(pwalletMain, "", strBackupWarning, strBackupError)) { + if(!AutoBackupWallet(vpwallets[0], "", strBackupWarning, strBackupError)) { if (!strBackupWarning.empty()) { // It's still more or less safe to continue but warn user anyway LogPrintf("OverviewPage::privateSendStatus -- WARNING! Something went wrong on automatic backup: %s\n", strBackupWarning); diff --git a/src/util.cpp b/src/util.cpp index 581b1faf48d2..7531b6799e71 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -568,6 +568,7 @@ void ArgsManager::ForceSetArg(const std::string& strArg, const std::string& strV { LOCK(cs_args); mapArgs[strArg] = strValue; + mapMultiArgs[strArg].clear(); mapMultiArgs[strArg].push_back(strValue); } diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp index 67f9f223f01d..3f96eee572b4 100644 --- a/src/wallet/db.cpp +++ b/src/wallet/db.cpp @@ -142,7 +142,7 @@ void CDBEnv::MakeMock() fMockDb = true; } -CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile)) +CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename) { LOCK(cs_db); assert(mapFileUseCount.count(strFile) == 0); @@ -155,21 +155,21 @@ CDBEnv::VerifyResult CDBEnv::Verify(const std::string& strFile, bool (*recoverFu return RECOVER_FAIL; // Try to recover: - bool fRecovered = (*recoverFunc)(strFile); + bool fRecovered = (*recoverFunc)(strFile, out_backup_filename); return (fRecovered ? RECOVER_OK : RECOVER_FAIL); } -bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)) +bool CDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& newFilename) { // Recovery procedure: - // move wallet file to wallet.timestamp.bak + // move wallet file to walletfilename.timestamp.bak // Call Salvage with fAggressive=true to // get as much data as possible. // Rewrite salvaged data to fresh wallet file // Set -rescan so any missing transactions will be // found. int64_t now = GetTime(); - std::string newFilename = strprintf("wallet.%d.bak", now); + newFilename = strprintf("%s.%d.bak", filename, now); int result = bitdb.dbenv->dbrename(NULL, filename.c_str(), NULL, newFilename.c_str(), DB_AUTO_COMMIT); @@ -259,18 +259,19 @@ bool CDB::VerifyEnvironment(const std::string& walletFile, const fs::path& dataD return true; } -bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)) +bool CDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc) { if (fs::exists(dataDir / walletFile)) { - CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc); + std::string backup_filename; + CDBEnv::VerifyResult r = bitdb.Verify(walletFile, recoverFunc, backup_filename); if (r == CDBEnv::RECOVER_OK) { warningStr = strprintf(_("Warning: Wallet file corrupt, data salvaged!" " Original %s saved as %s in %s; if" " your balance or transactions are incorrect you should" " restore from a backup."), - walletFile, "wallet.{timestamp}.bak", dataDir); + walletFile, backup_filename, dataDir); } if (r == CDBEnv::RECOVER_FAIL) { @@ -432,6 +433,11 @@ void CDB::Flush() env->dbenv->txn_checkpoint(nMinutes ? gArgs.GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0); } +void CWalletDBWrapper::IncrementUpdateCounter() +{ + ++nUpdateCounter; +} + void CDB::Close() { if (!pdb) diff --git a/src/wallet/db.h b/src/wallet/db.h index e4d8a5154d13..b220b0667698 100644 --- a/src/wallet/db.h +++ b/src/wallet/db.h @@ -55,7 +55,8 @@ class CDBEnv enum VerifyResult { VERIFY_OK, RECOVER_OK, RECOVER_FAIL }; - VerifyResult Verify(const std::string& strFile, bool (*recoverFunc)(const std::string& strFile)); + typedef bool (*recoverFunc_type)(const std::string& strFile, std::string& out_backup_filename); + VerifyResult Verify(const std::string& strFile, recoverFunc_type recoverFunc, std::string& out_backup_filename); /** * Salvage data from a file that Verify says is bad. * fAggressive sets the DB_AGGRESSIVE flag (see berkeley DB->verify() method documentation). @@ -93,13 +94,13 @@ class CWalletDBWrapper friend class CDB; public: /** Create dummy DB handle */ - CWalletDBWrapper(): env(nullptr) + CWalletDBWrapper() : nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(nullptr) { } /** Create DB handle to real database */ - CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in): - env(env_in), strFile(strFile_in) + CWalletDBWrapper(CDBEnv *env_in, const std::string &strFile_in) : + nLastSeen(0), nLastFlushed(0), nLastWalletUpdate(0), env(env_in), strFile(strFile_in) { } @@ -119,6 +120,13 @@ class CWalletDBWrapper */ void Flush(bool shutdown); + void IncrementUpdateCounter(); + + std::atomic nUpdateCounter; + unsigned int nLastSeen; + unsigned int nLastFlushed; + int64_t nLastWalletUpdate; + private: /** BerkeleyDB specific */ CDBEnv *env; @@ -149,7 +157,7 @@ class CDB void Flush(); void Close(); - static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)); + static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename); /* flush the wallet passively (TRY_LOCK) ideal to be called periodically */ @@ -157,7 +165,7 @@ class CDB /* verifies the database environment */ static bool VerifyEnvironment(const std::string& walletFile, const fs::path& dataDir, std::string& errorStr); /* verifies the database file */ - static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, bool (*recoverFunc)(const std::string& strFile)); + static bool VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr, CDBEnv::recoverFunc_type recoverFunc); private: CDB(const CDB&); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 39a8267c81e0..d0ad5351fe8c 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -32,7 +32,8 @@ CWallet *GetWalletForJSONRPCRequest(const JSONRPCRequest& request) { - return pwalletMain; + // TODO: Some way to access secondary wallets + return vpwallets.empty() ? nullptr : vpwallets[0]; } std::string HelpRequiringPassphrase(CWallet * const pwallet) diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp index 1989bf8d9b96..922fcc8e898d 100644 --- a/src/wallet/test/wallet_test_fixture.cpp +++ b/src/wallet/test/wallet_test_fixture.cpp @@ -8,6 +8,8 @@ #include "wallet/db.h" #include "wallet/wallet.h" +CWallet *pwalletMain; + WalletTestingSetup::WalletTestingSetup(const std::string& chainName): TestingSetup(chainName) { diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 76e322c9cf46..2181a95f373e 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -17,6 +17,8 @@ #include #include +extern CWallet* pwalletMain; + extern UniValue importmulti(const JSONRPCRequest& request); extern UniValue dumpwallet(const JSONRPCRequest& request); extern UniValue importwallet(const JSONRPCRequest& request); @@ -400,8 +402,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) // after. { CWallet wallet; - CWallet *backup = ::pwalletMain; - ::pwalletMain = &wallet; + vpwallets.insert(vpwallets.begin(), &wallet); UniValue keys; keys.setArray(); UniValue key; @@ -432,7 +433,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) "downloading and rescanning the relevant blocks (see -reindex and -rescan " "options).\"}},{\"success\":true}]", 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); - ::pwalletMain = backup; + vpwallets.erase(vpwallets.begin()); } } @@ -442,7 +443,6 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup) // than or equal to key birthday. BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) { - CWallet *pwalletMainBackup = ::pwalletMain; // Create two blocks with same timestamp to verify that importwallet rescan // will pick up both blocks, not just the first. const int64_t BLOCK_TIME = chainActive.Tip()->GetBlockTimeMax() + 5; @@ -468,7 +468,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); request.params.push_back("wallet.backup"); - ::pwalletMain = &wallet; + vpwallets.insert(vpwallets.begin(), &wallet); ::dumpwallet(request); } @@ -480,7 +480,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) JSONRPCRequest request; request.params.setArray(); request.params.push_back("wallet.backup"); - ::pwalletMain = &wallet; + vpwallets[0] = &wallet; ::importwallet(request); BOOST_CHECK_EQUAL(wallet.mapWallet.size(), 3); @@ -493,7 +493,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) } SetMockTime(0); - ::pwalletMain = pwalletMainBackup; + vpwallets.erase(vpwallets.begin()); } // Check that GetImmatureCredit() returns a newly calculated value instead of diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 976d55f7b5c0..1089d4557dbf 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -45,7 +45,7 @@ #include #include -CWallet* pwalletMain = NULL; +std::vector vpwallets; /** Transaction fee set by the user */ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; @@ -606,30 +606,40 @@ bool CWallet::Verify() if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; - uiInterface.InitMessage(_("Verifying wallet...")); - std::string walletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT); + uiInterface.InitMessage(_("Verifying wallet(s)...")); - std::string strError; - if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) - return InitError(strError); + for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { + if (boost::filesystem::path(walletFile).filename() != walletFile) { + return InitError(_("-wallet parameter must only specify a filename (not a path)")); + } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { + return InitError(_("Invalid characters in -wallet filename")); + } - if (gArgs.GetBoolArg("-salvagewallet", false)) - { - // Recover readable keypairs: - CWallet dummyWallet; - if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter)) + std::string strError; + if (!CWalletDB::VerifyEnvironment(walletFile, GetDataDir().string(), strError)) { + return InitError(strError); + } + + if (gArgs.GetBoolArg("-salvagewallet", false)) { + // Recover readable keypairs: + CWallet dummyWallet; + std::string backup_filename; + if (!CWalletDB::Recover(walletFile, (void *)&dummyWallet, CWalletDB::RecoverKeysOnlyFilter, backup_filename)) { + return false; + } + } + + std::string strWarning; + bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); + if (!strWarning.empty()) { + InitWarning(strWarning); + } + if (!dbV) { + InitError(strError); return false; + } } - std::string strWarning; - bool dbV = CWalletDB::VerifyDatabaseFile(walletFile, GetDataDir().string(), strWarning, strError); - if (!strWarning.empty()) - InitWarning(strWarning); - if (!dbV) - { - InitError(strError); - return false; - } return true; } @@ -3817,8 +3827,9 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry) bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwalletdb) { - if (!pwalletdb->WriteAccountingEntry_Backend(acentry)) + if (!pwalletdb->WriteAccountingEntry(++nAccountingEntryNumber, acentry)) { return false; + } laccentries.push_back(acentry); CAccountingEntry & entry = laccentries.back(); @@ -4927,7 +4938,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) walletInstance->ScanForWalletTransactions(pindexRescan, true); LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); walletInstance->SetBestChain(chainActive.GetLocator()); - CWalletDB::IncrementUpdateCounter(); + walletInstance->dbw->IncrementUpdateCounter(); // Restore wallet transaction metadata after -zapwallettxes=1 if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.GetArg("-zapwallettxes", "1") != "2") @@ -4970,24 +4981,17 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile) bool CWallet::InitLoadWallet() { if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) { - pwalletMain = NULL; LogPrintf("Wallet disabled!\n"); return true; } - std::string walletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT); - - if (boost::filesystem::path(walletFile).filename() != walletFile) { - return InitError(_("-wallet parameter must only specify a filename (not a path)")); - } else if (SanitizeString(walletFile, SAFE_CHARS_FILENAME) != walletFile) { - return InitError(_("Invalid characters in -wallet filename")); - } - - CWallet * const pwallet = CreateWalletFromFile(walletFile); - if (!pwallet) { - return false; + for (const std::string& walletFile : gArgs.GetArgs("-wallet")) { + CWallet * const pwallet = CreateWalletFromFile(walletFile); + if (!pwallet) { + return false; + } + vpwallets.push_back(pwallet); } - pwalletMain = pwallet; return true; } @@ -5008,6 +5012,9 @@ void CWallet::postInitProcess(CScheduler& scheduler) bool CWallet::ParameterInteraction() { + gArgs.SoftSetArg("-wallet", DEFAULT_WALLET_DAT); + const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1; + if (gArgs.GetBoolArg("-disablewallet", DEFAULT_DISABLE_WALLET)) return true; @@ -5016,15 +5023,27 @@ bool CWallet::ParameterInteraction() } if (gArgs.GetBoolArg("-salvagewallet", false) && gArgs.SoftSetBoolArg("-rescan", true)) { + if (is_multiwallet) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-salvagewallet")); + } // Rewrite just private keys: rescan to find transactions LogPrintf("%s: parameter interaction: -salvagewallet=1 -> setting -rescan=1\n", __func__); } // -zapwallettx implies a rescan if (gArgs.GetBoolArg("-zapwallettxes", false) && gArgs.SoftSetBoolArg("-rescan", true)) { + if (is_multiwallet) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-zapwallettxes")); + } LogPrintf("%s: parameter interaction: -zapwallettxes= -> setting -rescan=1\n", __func__); } + if (is_multiwallet) { + if (gArgs.GetBoolArg("-upgradewallet", false)) { + return InitError(strprintf("%s is only allowed with a single wallet file", "-upgradewallet")); + } + } + if (gArgs.GetBoolArg("-sysperms", false)) return InitError("-sysperms is not allowed in combination with enabled wallet functionality"); if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false)) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 283ead09236d..a8fbaf723013 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -34,7 +34,8 @@ #include #include -extern CWallet* pwalletMain; +typedef CWallet* CWalletRef; +extern std::vector vpwallets; /** * Settings @@ -841,6 +842,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface nMasterKeyMaxID = 0; pwalletdbEncryption = NULL; nOrderPosNext = 0; + nAccountingEntryNumber = 0; nNextResend = 0; nLastResend = 0; nTimeFirstKey = 0; @@ -862,6 +864,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface TxItems wtxOrdered; int64_t nOrderPosNext; + uint64_t nAccountingEntryNumber; std::map mapRequestCount; std::map mapAddressBook; diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index ec6871036470..627089e737d5 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -22,59 +22,47 @@ #include #include -static uint64_t nAccountingEntryNumber = 0; - -static std::atomic nWalletDBUpdateCounter; - // // CWalletDB // bool CWalletDB::WriteName(const std::string& strAddress, const std::string& strName) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("name"), strAddress), strName); + return WriteIC(std::make_pair(std::string("name"), strAddress), strName); } bool CWalletDB::EraseName(const std::string& strAddress) { // This should only be used for sending addresses, never for receiving addresses, // receiving addresses must always have an address book entry if they're not change return. - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("name"), strAddress)); + return EraseIC(std::make_pair(std::string("name"), strAddress)); } bool CWalletDB::WritePurpose(const std::string& strAddress, const std::string& strPurpose) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("purpose"), strAddress), strPurpose); + return WriteIC(std::make_pair(std::string("purpose"), strAddress), strPurpose); } bool CWalletDB::ErasePurpose(const std::string& strPurpose) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("purpose"), strPurpose)); + return EraseIC(std::make_pair(std::string("purpose"), strPurpose)); } bool CWalletDB::WriteTx(const CWalletTx& wtx) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); + return WriteIC(std::make_pair(std::string("tx"), wtx.GetHash()), wtx); } bool CWalletDB::EraseTx(uint256 hash) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("tx"), hash)); + return EraseIC(std::make_pair(std::string("tx"), hash)); } bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta) { - nWalletDBUpdateCounter++; - - if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey), - keyMeta, false)) + if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta, false)) { return false; + } // hash pubkey/privkey to accelerate wallet load std::vector vchKey; @@ -82,7 +70,7 @@ bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, c vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end()); - return batch.Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); + return WriteIC(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false); } bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, @@ -90,55 +78,53 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, const CKeyMetadata &keyMeta) { const bool fEraseUnencryptedKey = true; - nWalletDBUpdateCounter++; - if (!batch.Write(std::make_pair(std::string("keymeta"), vchPubKey), - keyMeta)) + if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) { return false; + } - if (!batch.Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) + if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) { return false; + } if (fEraseUnencryptedKey) { - batch.Erase(std::make_pair(std::string("key"), vchPubKey)); - batch.Erase(std::make_pair(std::string("wkey"), vchPubKey)); + EraseIC(std::make_pair(std::string("key"), vchPubKey)); + EraseIC(std::make_pair(std::string("wkey"), vchPubKey)); } + return true; } bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true); + return WriteIC(std::make_pair(std::string("mkey"), nID), kMasterKey, true); } bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); + return WriteIC(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false); } bool CWalletDB::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta) { - nWalletDBUpdateCounter++; - if (!batch.Write(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) + if (!WriteIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)), keyMeta)) { return false; - return batch.Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); + } + return WriteIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1'); } bool CWalletDB::EraseWatchOnly(const CScript &dest) { - nWalletDBUpdateCounter++; - if (!batch.Erase(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) + if (!EraseIC(std::make_pair(std::string("watchmeta"), *(const CScriptBase*)(&dest)))) { return false; - return batch.Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); + } + return EraseIC(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest))); } bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) { - nWalletDBUpdateCounter++; - batch.Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan - return batch.Write(std::string("bestblock_nomerkle"), locator); + WriteIC(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan + return WriteIC(std::string("bestblock_nomerkle"), locator); } bool CWalletDB::ReadBestBlock(CBlockLocator& locator) @@ -149,14 +135,12 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator) bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("orderposnext"), nOrderPosNext); + return WriteIC(std::string("orderposnext"), nOrderPosNext); } bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("defaultkey"), vchPubKey); + return WriteIC(std::string("defaultkey"), vchPubKey); } bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool) @@ -166,19 +150,17 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool) bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("pool"), nPool), keypool); + return WriteIC(std::make_pair(std::string("pool"), nPool), keypool); } bool CWalletDB::ErasePool(int64_t nPool) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("pool"), nPool)); + return EraseIC(std::make_pair(std::string("pool"), nPool)); } bool CWalletDB::WriteMinVersion(int nVersion) { - return batch.Write(std::string("minversion"), nVersion); + return WriteIC(std::string("minversion"), nVersion); } bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account) @@ -189,17 +171,12 @@ bool CWalletDB::ReadAccount(const std::string& strAccount, CAccount& account) bool CWalletDB::WriteAccount(const std::string& strAccount, const CAccount& account) { - return batch.Write(std::make_pair(std::string("acc"), strAccount), account); + return WriteIC(std::make_pair(std::string("acc"), strAccount), account); } bool CWalletDB::WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry) { - return batch.Write(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); -} - -bool CWalletDB::WriteAccountingEntry_Backend(const CAccountingEntry& acentry) -{ - return WriteAccountingEntry(++nAccountingEntryNumber, acentry); + return WriteIC(std::make_pair(std::string("acentry"), std::make_pair(acentry.strAccount, nAccEntryNum)), acentry); } CAmount CWalletDB::GetAccountCreditDebit(const std::string& strAccount) @@ -338,8 +315,9 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, ssKey >> strAccount; uint64_t nNumber; ssKey >> nNumber; - if (nNumber > nAccountingEntryNumber) - nAccountingEntryNumber = nNumber; + if (nNumber > pwallet->nAccountingEntryNumber) { + pwallet->nAccountingEntryNumber = nNumber; + } if (!wss.fAnyUnordered) { @@ -818,38 +796,39 @@ void MaybeCompactWalletDB() return; } - static unsigned int nLastSeen = CWalletDB::GetUpdateCounter(); - static unsigned int nLastFlushed = CWalletDB::GetUpdateCounter(); - static int64_t nLastWalletUpdate = GetTime(); + for (CWalletRef pwallet : vpwallets) { + CWalletDBWrapper& dbh = pwallet->GetDBHandle(); - if (nLastSeen != CWalletDB::GetUpdateCounter()) - { - nLastSeen = CWalletDB::GetUpdateCounter(); - nLastWalletUpdate = GetTime(); - } + unsigned int nUpdateCounter = dbh.nUpdateCounter; - if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2) - { - if (CDB::PeriodicFlush(pwalletMain->GetDBHandle())) { - nLastFlushed = CWalletDB::GetUpdateCounter(); + if (dbh.nLastSeen != nUpdateCounter) { + dbh.nLastSeen = nUpdateCounter; + dbh.nLastWalletUpdate = GetTime(); + } + + if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) { + if (CDB::PeriodicFlush(dbh)) { + dbh.nLastFlushed = nUpdateCounter; + } } } + fOneThread = false; } // // Try to (very carefully!) recover wallet file if there is a problem. // -bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)) +bool CWalletDB::Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename) { - return CDB::Recover(filename, callbackDataIn, recoverKVcallback); + return CDB::Recover(filename, callbackDataIn, recoverKVcallback, out_backup_filename); } -bool CWalletDB::Recover(const std::string& filename) +bool CWalletDB::Recover(const std::string& filename, std::string& out_backup_filename) { // recover without a key filter callback // results in recovering all record types - return CWalletDB::Recover(filename, NULL, NULL); + return CWalletDB::Recover(filename, NULL, NULL, out_backup_filename); } bool CWalletDB::RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue) @@ -882,57 +861,40 @@ bool CWalletDB::VerifyEnvironment(const std::string& walletFile, const fs::path& bool CWalletDB::VerifyDatabaseFile(const std::string& walletFile, const fs::path& dataDir, std::string& warningStr, std::string& errorStr) { - return CDB::VerifyDatabaseFile(walletFile, dataDir, errorStr, warningStr, CWalletDB::Recover); + return CDB::VerifyDatabaseFile(walletFile, dataDir, warningStr, errorStr, CWalletDB::Recover); } bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value) { - nWalletDBUpdateCounter++; - return batch.Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); + return WriteIC(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value); } bool CWalletDB::EraseDestData(const std::string &address, const std::string &key) { - nWalletDBUpdateCounter++; - return batch.Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key))); + return EraseIC(std::make_pair(std::string("destdata"), std::make_pair(address, key))); } bool CWalletDB::WriteHDChain(const CHDChain& chain) { - nWalletDBUpdateCounter++; - return batch.Write(std::string("hdchain"), chain); + return WriteIC(std::string("hdchain"), chain); } bool CWalletDB::WriteCryptedHDChain(const CHDChain& chain) { - nWalletDBUpdateCounter++; - - if (!batch.Write(std::string("chdchain"), chain)) + if (!WriteIC(std::string("chdchain"), chain)) return false; - batch.Erase(std::string("hdchain")); + EraseIC(std::string("hdchain")); return true; } bool CWalletDB::WriteHDPubKey(const CHDPubKey& hdPubKey, const CKeyMetadata& keyMeta) { - nWalletDBUpdateCounter++; - - if (!batch.Write(std::make_pair(std::string("keymeta"), hdPubKey.extPubKey.pubkey), keyMeta, false)) + if (!WriteIC(std::make_pair(std::string("keymeta"), hdPubKey.extPubKey.pubkey), keyMeta, false)) return false; - return batch.Write(std::make_pair(std::string("hdpubkey"), hdPubKey.extPubKey.pubkey), hdPubKey, false); -} - -void CWalletDB::IncrementUpdateCounter() -{ - nWalletDBUpdateCounter++; -} - -unsigned int CWalletDB::GetUpdateCounter() -{ - return nWalletDBUpdateCounter; + return WriteIC(std::make_pair(std::string("hdpubkey"), hdPubKey.extPubKey.pubkey), hdPubKey, false); } bool CWalletDB::TxnBegin() diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index fd9da46be559..520ee56e6fac 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -95,9 +95,31 @@ class CKeyMetadata */ class CWalletDB { +private: + template + bool WriteIC(const K& key, const T& value, bool fOverwrite = true) + { + if (!batch.Write(key, value, fOverwrite)) { + return false; + } + m_dbw.IncrementUpdateCounter(); + return true; + } + + template + bool EraseIC(const K& key) + { + if (!batch.Erase(key)) { + return false; + } + m_dbw.IncrementUpdateCounter(); + return true; + } + public: CWalletDB(CWalletDBWrapper& dbw, const char* pszMode = "r+", bool _fFlushOnClose = true) : - batch(dbw, pszMode, _fFlushOnClose) + batch(dbw, pszMode, _fFlushOnClose), + m_dbw(dbw) { } @@ -135,7 +157,6 @@ class CWalletDB /// This writes directly to the database, and will not update the CWallet's cached accounting entries! /// Use wallet.AddAccountingEntry instead, to write *and* update its caches. bool WriteAccountingEntry(const uint64_t nAccEntryNum, const CAccountingEntry& acentry); - bool WriteAccountingEntry_Backend(const CAccountingEntry& acentry); bool ReadAccount(const std::string& strAccount, CAccount& account); bool WriteAccount(const std::string& strAccount, const CAccount& account); @@ -152,9 +173,9 @@ class CWalletDB DBErrors ZapWalletTx(std::vector& vWtx); DBErrors ZapSelectTx(std::vector& vHashIn, std::vector& vHashOut); /* Try to (very carefully!) recover wallet database (with a possible key type filter) */ - static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue)); + static bool Recover(const std::string& filename, void *callbackDataIn, bool (*recoverKVcallback)(void* callbackData, CDataStream ssKey, CDataStream ssValue), std::string& out_backup_filename); /* Recover convenience-function to bypass the key filter callback, called when verify fails, recovers everything */ - static bool Recover(const std::string& filename); + static bool Recover(const std::string& filename, std::string& out_backup_filename); /* Recover filter (used as callback), will only let keys (cryptographical keys) as KV/key-type pass through */ static bool RecoverKeysOnlyFilter(void *callbackData, CDataStream ssKey, CDataStream ssValue); /* Function to determine if a certain KV/key-type is a key (cryptographical key) type */ @@ -169,9 +190,6 @@ class CWalletDB bool WriteCryptedHDChain(const CHDChain& chain); bool WriteHDPubKey(const CHDPubKey& hdPubKey, const CKeyMetadata& keyMeta); - static void IncrementUpdateCounter(); - static unsigned int GetUpdateCounter(); - //! Begin a new transaction bool TxnBegin(); //! Commit current transaction @@ -184,6 +202,7 @@ class CWalletDB bool WriteVersion(int nVersion); private: CDB batch; + CWalletDBWrapper& m_dbw; CWalletDB(const CWalletDB&); void operator=(const CWalletDB&); From d46aff53699942363364f056b1d63ef04e5caf49 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 20 Jun 2017 16:07:53 -0700 Subject: [PATCH 397/987] Merge #10536: Remove unreachable or otherwise redundant code 4265bf351 Remove unreachable or otherwise redundant code (practicalswift) Tree-SHA512: bc9666ab5d20c936d78c50c0361405aca9edd116602aa9bcd71a79a904b647ac9eca0651d1a9d530189a6ac1c4e235bfc69ec1a68f7e36cc14d6848ac2206b7b --- src/dash-tx.cpp | 1 - src/qt/test/rpcnestedtests.cpp | 2 -- src/wallet/crypter.cpp | 1 - src/wallet/wallet.cpp | 3 --- src/wallet/walletdb.cpp | 10 ++-------- 5 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/dash-tx.cpp b/src/dash-tx.cpp index 420a39a4aaef..70322e01de47 100644 --- a/src/dash-tx.cpp +++ b/src/dash-tx.cpp @@ -281,7 +281,6 @@ static void MutateTxAddOutPubKey(CMutableTransaction& tx, const std::string& str if (!pubkey.IsFullyValid()) throw std::runtime_error("invalid TX output pubkey"); CScript scriptPubKey = GetScriptForRawPubKey(pubkey); - CBitcoinAddress addr(scriptPubKey); // Extract and validate FLAGS bool bScriptHash = false; diff --git a/src/qt/test/rpcnestedtests.cpp b/src/qt/test/rpcnestedtests.cpp index ff78b6f04045..723c183bdd5b 100644 --- a/src/qt/test/rpcnestedtests.cpp +++ b/src/qt/test/rpcnestedtests.cpp @@ -36,8 +36,6 @@ static const CRPCCommand vRPCCommands[] = void RPCNestedTests::rpcNestedTests() { - UniValue jsonRPCError; - // do some test setup // could be moved to a more generic place when we add more tests on QT level const CChainParams& chainparams = Params(); diff --git a/src/wallet/crypter.cpp b/src/wallet/crypter.cpp index 1f54d7430444..83279e2e2438 100644 --- a/src/wallet/crypter.cpp +++ b/src/wallet/crypter.cpp @@ -337,7 +337,6 @@ bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) co // Check for watch-only pubkeys return CBasicKeyStore::GetPubKey(address, vchPubKeyOut); } - return false; } bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index aabb222f7e1c..163a68abeeea 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -327,7 +327,6 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); } - return false; } bool CWallet::LoadKeyMetadata(const CTxDestination& keyID, const CKeyMetadata &meta) @@ -3662,8 +3661,6 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT return false; } - CTransaction txNewConst(txNew); - // Remove scriptSigs to eliminate the fee calculation dummy signatures for (auto& txin : txNew.vin) { txin.scriptSig = CScript(); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 9aadaaff784c..49edb91d2fa9 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -77,8 +77,6 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, const std::vector& vchCryptedSecret, const CKeyMetadata &keyMeta) { - const bool fEraseUnencryptedKey = true; - if (!WriteIC(std::make_pair(std::string("keymeta"), vchPubKey), keyMeta)) { return false; } @@ -86,12 +84,8 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey, if (!WriteIC(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false)) { return false; } - if (fEraseUnencryptedKey) - { - EraseIC(std::make_pair(std::string("key"), vchPubKey)); - EraseIC(std::make_pair(std::string("wkey"), vchPubKey)); - } - + EraseIC(std::make_pair(std::string("key"), vchPubKey)); + EraseIC(std::make_pair(std::string("wkey"), vchPubKey)); return true; } From 43c952d2eb3da8ee5087b31044c81592c456bd3b Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Thu, 22 Jun 2017 10:50:24 +0200 Subject: [PATCH 398/987] Merge #10632: qa: Add stopatheight test 5555fa8 qa: Add stopatheight test (MarcoFalke) Tree-SHA512: ea3f318c3dc73a885db5e258f5d6a25e0017e2360a72ac5f6914bce6f7798d36aca45d2626aafd57ead744bd28fd38b561207a7a547a1d417e594976c35bccee --- test/functional/blockchain.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 8dc500e6caea..f7506d50d314 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -18,13 +18,16 @@ """ from decimal import Decimal +import subprocess from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, + assert_raises, assert_raises_jsonrpc, assert_is_hex_string, assert_is_hash_string, + bitcoind_processes, ) @@ -34,6 +37,7 @@ def __init__(self): super().__init__() self.setup_clean_chain = False self.num_nodes = 1 + self.extra_args = [['-stopatheight=207']] def run_test(self): self._test_getchaintxstats() @@ -41,7 +45,8 @@ def run_test(self): self._test_getblockheader() self._test_getdifficulty() self._test_getnetworkhashps() - self.nodes[0].verifychain(4, 0) + self._test_stopatheight() + assert self.nodes[0].verifychain(4, 0) def _test_getchaintxstats(self): chaintxstats = self.nodes[0].getchaintxstats(1) @@ -128,5 +133,18 @@ def _test_getnetworkhashps(self): # This should be 2 hashes every 2.6 minutes (156 seconds) or 1/78 assert abs(hashes_per_second * 78 - 1) < 0.0001 + def _test_stopatheight(self): + assert_equal(self.nodes[0].getblockcount(), 200) + self.nodes[0].generate(6) + assert_equal(self.nodes[0].getblockcount(), 206) + self.log.debug('Node should not stop at this height') + assert_raises(subprocess.TimeoutExpired, lambda: bitcoind_processes[0].wait(timeout=3)) + self.nodes[0].generate(1) + self.log.debug('Node should stop at this height...') + bitcoind_processes[0].wait(timeout=3) + self.nodes[0] = self.start_node(0, self.options.tmpdir) + assert_equal(self.nodes[0].getblockcount(), 207) + + if __name__ == '__main__': BlockchainTest().main() From 6b6ea2461847d71ec7179e11f21660b3f9db1d51 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 Jun 2017 16:10:58 +0200 Subject: [PATCH 399/987] Merge #10642: Remove obsolete _MSC_VER check 700d8d8 Remove obsolete _MSC_VER check (practicalswift) Tree-SHA512: 3b33f3ce90a3b3b6abec74990fab88402f896402fc563b7081575f85dab05fc7e21fd4c640ca4b9a57a6ca01c5c8ca931be37cac6fa62968fc7b84c719ec6ede --- src/init.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 1d6b1012ffc2..a5270b6000e5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1054,8 +1054,6 @@ bool AppInitBasicSetup() // Turn off Microsoft heap dump noise _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0)); -#endif -#if _MSC_VER >= 1400 // Disable confusing "helpful" text message on abort, Ctrl-C _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); #endif From 41302bbae055aefdad9ac4e59894af77c87bac28 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 Jun 2017 16:25:50 +0200 Subject: [PATCH 400/987] Merge #10628: [depends] expat 2.2.1 2c3fc51 [depends] expat 2.2.1 (fanquake) Tree-SHA512: ad0e18f2770c0c4b378123bcbcf93ed0ee0b03dbf6360f02e88b01052ef7b0f5540a0a5cbb6d0d3a3d70db29b0413a43f17e7fa5092185fb874470a9f6be4d76 --- depends/packages/expat.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/packages/expat.mk b/depends/packages/expat.mk index 81a660e83a55..7f484724a490 100644 --- a/depends/packages/expat.mk +++ b/depends/packages/expat.mk @@ -1,8 +1,8 @@ package=expat -$(package)_version=2.2.0 +$(package)_version=2.2.1 $(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version) $(package)_file_name=$(package)-$($(package)_version).tar.bz2 -$(package)_sha256_hash=d9e50ff2d19b3538bd2127902a89987474e1a4db8e43a66a4d1a712ab9a504ff +$(package)_sha256_hash=1868cadae4c82a018e361e2b2091de103cd820aaacb0d6cfa49bd2cd83978885 define $(package)_set_vars $(package)_config_opts=--disable-static From a3abc463f96972187f6d7c13e2f1ab38986676e6 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 Jun 2017 17:10:16 +0200 Subject: [PATCH 401/987] Merge #10530: Fix invalid instantiation and possibly unsafe accesses of array in class base_uint e5c6168 Fix instantiation and array accesses in class base_uint (Pavlos Antoniou) Tree-SHA512: e4d39510d776c5ae8814cd5fb5c5d183cd8da937e339bff95caff68a84492fbec68bf513c5a6267446a564d39093e0c7fc703c645b511caab80f7baf7955b804 --- src/arith_uint256.cpp | 2 ++ src/arith_uint256.h | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index 64c9dc2bb851..1755b72a8356 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -15,6 +15,8 @@ template base_uint::base_uint(const std::string& str) { + static_assert(BITS/32 > 0 && BITS%32 == 0, "Template parameter BITS must be a positive multiple of 32."); + SetHex(str); } diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 5cc52f6e72af..52a4747c1586 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -31,12 +31,16 @@ class base_uint base_uint() { + static_assert(BITS/32 > 0 && BITS%32 == 0, "Template parameter BITS must be a positive multiple of 32."); + for (int i = 0; i < WIDTH; i++) pn[i] = 0; } base_uint(const base_uint& b) { + static_assert(BITS/32 > 0 && BITS%32 == 0, "Template parameter BITS must be a positive multiple of 32."); + for (int i = 0; i < WIDTH; i++) pn[i] = b.pn[i]; } @@ -50,6 +54,8 @@ class base_uint base_uint(uint64_t b) { + static_assert(BITS/32 > 0 && BITS%32 == 0, "Template parameter BITS must be a positive multiple of 32."); + pn[0] = (unsigned int)b; pn[1] = (unsigned int)(b >> 32); for (int i = 2; i < WIDTH; i++) @@ -174,7 +180,7 @@ class base_uint { // prefix operator int i = 0; - while (++pn[i] == 0 && i < WIDTH-1) + while (i < WIDTH && ++pn[i] == 0) i++; return *this; } @@ -191,7 +197,7 @@ class base_uint { // prefix operator int i = 0; - while (--pn[i] == (uint32_t)-1 && i < WIDTH-1) + while (i < WIDTH && --pn[i] == (uint32_t)-1) i++; return *this; } From 1c4981d719bdff018f039022ea0c08c01467cb04 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 Jun 2017 17:55:51 +0200 Subject: [PATCH 402/987] Merge #9343: Don't create change at dust limit 6171826 Don't create change at the dust limit, even if it means paying more than expected (Alex Morcos) Tree-SHA512: d4cf939b97a92d63d4703ad152093c9dc60e74af590697bc21adbcdf17fc9e6ffb37d46d5eefafbd69327d1bcb79911f1b826ce1d960d895d464c4408c4995c3 --- src/qt/coincontroldialog.cpp | 11 ++++------- src/wallet/wallet.cpp | 24 +----------------------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index b8873d3c6eab..b28275ea050b 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -569,13 +569,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) CTxOut txout(nChange, (CScript)std::vector(24, 0)); if (IsDust(txout, ::dustRelayFee)) { - if (CoinControlDialog::fSubtractFeeFromAmount) // dust-change will be raised until no dust - nChange = GetDustThreshold(txout, ::dustRelayFee); - else - { - nPayFee += nChange; - nChange = 0; - } + nPayFee += nChange; + nChange = 0; + if (CoinControlDialog::fSubtractFeeFromAmount) + nBytes -= 34; // we didn't detect lack of change above } } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 163a68abeeea..867ac186bc35 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3550,29 +3550,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT newTxOut = CTxOut(nChange, scriptChange); - // We do not move dust-change to fees, because the sender would end up paying more than requested. - // This would be against the purpose of the all-inclusive feature. - // So instead we raise the change and deduct from the recipient. - if (nSubtractFeeFromAmount > 0 && IsDust(newTxOut, ::dustRelayFee)) - { - CAmount nDust = GetDustThreshold(newTxOut, ::dustRelayFee) - newTxOut.nValue; - newTxOut.nValue += nDust; // raise change until no more dust - for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient - { - if (vecSend[i].fSubtractFeeFromAmount) - { - txNew.vout[i].nValue -= nDust; - if (IsDust(txNew.vout[i], ::dustRelayFee)) - { - strFailReason = _("The transaction amount is too small to send after the fee has been deducted"); - return false; - } - break; - } - } - } - - // Never create dust outputs; if we would, just + // Never create dust outputs; if we would, just // add the dust to the fee. if (IsDust(newTxOut, ::dustRelayFee)) { From 31f4a602a5859fc6608a5ef36ea348ad102d8360 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 Jun 2017 18:35:39 +0200 Subject: [PATCH 403/987] Merge #9517: [refactor] Switched httpserver.cpp to use RAII wrapped libevents. 1ae86ec Changed event RAII helper functions to inline to deal with duplicate symbol linker errors. (Karl-Johan Alm) fd369d2 Switched httpserver.cpp to use RAII wrapped libevents. (Kalle Alm) Tree-SHA512: 877e431f211024d42a3b0800e860e02833398611433e8393f8d5d4970f47f4bd670b900443678c067fec110c087aaab7dc1981ccbf17f6057676fdbbda89aed9 --- src/httpserver.cpp | 24 ++++++++---------------- src/support/events.h | 10 +++++----- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 7b8c21c9a649..a53731880b60 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -21,13 +21,13 @@ #include #include -#include -#include #include #include #include #include +#include "support/events.h" + #ifdef EVENT__HAVE_NETINET_IN_H #include #ifdef _XOPEN_SOURCE_EXTENDED @@ -369,9 +369,6 @@ static void libevent_log_cb(int severity, const char *msg) bool InitHTTPServer() { - struct evhttp* http = 0; - struct event_base* base = 0; - if (!InitHTTPAllowList()) return false; @@ -397,17 +394,13 @@ bool InitHTTPServer() evthread_use_pthreads(); #endif - base = event_base_new(); // XXX RAII - if (!base) { - LogPrintf("Couldn't create an event_base: exiting\n"); - return false; - } + raii_event_base base_ctr = obtain_event_base(); /* Create a new evhttp object to handle requests. */ - http = evhttp_new(base); // XXX RAII + raii_evhttp http_ctr = obtain_evhttp(base_ctr.get()); + struct evhttp* http = http_ctr.get(); if (!http) { LogPrintf("couldn't create evhttp. Exiting.\n"); - event_base_free(base); return false; } @@ -418,8 +411,6 @@ bool InitHTTPServer() if (!HTTPBindAddresses(http)) { LogPrintf("Unable to bind any endpoint for RPC server\n"); - evhttp_free(http); - event_base_free(base); return false; } @@ -428,8 +419,9 @@ bool InitHTTPServer() LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth); workQueue = new WorkQueue(workQueueDepth); - eventBase = base; - eventHTTP = http; + // tranfer ownership to eventBase/HTTP via .release() + eventBase = base_ctr.release(); + eventHTTP = http_ctr.release(); return true; } diff --git a/src/support/events.h b/src/support/events.h index 4f2f3cf9ef76..90690876eee0 100644 --- a/src/support/events.h +++ b/src/support/events.h @@ -27,26 +27,26 @@ MAKE_RAII(evhttp); MAKE_RAII(evhttp_request); MAKE_RAII(evhttp_connection); -raii_event_base obtain_event_base() { +inline raii_event_base obtain_event_base() { auto result = raii_event_base(event_base_new()); if (!result.get()) throw std::runtime_error("cannot create event_base"); return result; } -raii_event obtain_event(struct event_base* base, evutil_socket_t s, short events, event_callback_fn cb, void* arg) { +inline raii_event obtain_event(struct event_base* base, evutil_socket_t s, short events, event_callback_fn cb, void* arg) { return raii_event(event_new(base, s, events, cb, arg)); } -raii_evhttp obtain_evhttp(struct event_base* base) { +inline raii_evhttp obtain_evhttp(struct event_base* base) { return raii_evhttp(evhttp_new(base)); } -raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg) { +inline raii_evhttp_request obtain_evhttp_request(void(*cb)(struct evhttp_request *, void *), void *arg) { return raii_evhttp_request(evhttp_request_new(cb, arg)); } -raii_evhttp_connection obtain_evhttp_connection_base(struct event_base* base, std::string host, uint16_t port) { +inline raii_evhttp_connection obtain_evhttp_connection_base(struct event_base* base, std::string host, uint16_t port) { auto result = raii_evhttp_connection(evhttp_connection_base_new(base, NULL, host.c_str(), port)); if (!result.get()) throw std::runtime_error("create connection failed"); From 2116e930195ae139d39eeed73fafa796406fc7c8 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 Jun 2017 19:33:00 +0200 Subject: [PATCH 404/987] Merge #10276: contrib/verifybinaries: allow filtering by platform 8d4dafd contrib/verifybinaries: allow filtering by platform (Andres G. Aragoneses) Tree-SHA512: 5c117d18fd6e73cdbbf39c610f521bccb32ca7100eb8d5d5ed9c664514c37b32bd2f94f357b64c34f7c093e0c09312ecff330b7f5c708700d4b48643780ebac5 --- contrib/verifybinaries/README.md | 8 ++++++ contrib/verifybinaries/verify.sh | 43 ++++++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/contrib/verifybinaries/README.md b/contrib/verifybinaries/README.md index ed3e14fb6c11..3ffe0a2f2895 100644 --- a/contrib/verifybinaries/README.md +++ b/contrib/verifybinaries/README.md @@ -26,6 +26,14 @@ The script returns 0 if everything passes the checks. It returns 1 if either the ./verify.sh bitcoin-core-0.13.0-rc3 ``` +If you only want to download the binaries of certain platform, add the corresponding suffix, e.g.: + +```sh +./verify.sh bitcoin-core-0.11.2-osx +./verify.sh 0.12.0-linux +./verify.sh bitcoin-core-0.13.0-rc3-win64 +``` + If you do not want to keep the downloaded binaries, specify anything as the second parameter. ```sh diff --git a/contrib/verifybinaries/verify.sh b/contrib/verifybinaries/verify.sh index e20770c96a96..c2cc2b7013ad 100755 --- a/contrib/verifybinaries/verify.sh +++ b/contrib/verifybinaries/verify.sh @@ -42,13 +42,36 @@ if [ -n "$1" ]; then VERSION="$VERSIONPREFIX$1" fi - #now let's see if the version string contains "rc", and strip it off if it does - # and simultaneously add RCSUBDIR to BASEDIR, where we will look for SIGNATUREFILENAME - if [[ $VERSION == *"$RCVERSIONSTRING"* ]]; then - BASEDIR="$BASEDIR${VERSION/%-$RCVERSIONSTRING*}/" - BASEDIR="$BASEDIR$RCSUBDIR.$RCVERSIONSTRING${VERSION: -1}/" + STRIPPEDLAST="${VERSION%-*}" + + #now let's see if the version string contains "rc" or a platform name (e.g. "osx") + if [[ "$STRIPPEDLAST-" == "$VERSIONPREFIX" ]]; then + BASEDIR="$BASEDIR$VERSION/" else + # let's examine the last part to see if it's rc and/or platform name + STRIPPEDNEXTTOLAST="${STRIPPEDLAST%-*}" + if [[ "$STRIPPEDNEXTTOLAST-" == "$VERSIONPREFIX" ]]; then + + LASTSUFFIX="${VERSION##*-}" + VERSION="$STRIPPEDLAST" + + if [[ $LASTSUFFIX == *"$RCVERSIONSTRING"* ]]; then + RCVERSION="$LASTSUFFIX" + else + PLATFORM="$LASTSUFFIX" + fi + + else + RCVERSION="${STRIPPEDLAST##*-}" + PLATFORM="${VERSION##*-}" + + VERSION="$STRIPPEDNEXTTOLAST" + fi + BASEDIR="$BASEDIR$VERSION/" + if [[ $RCVERSION == *"$RCVERSIONSTRING"* ]]; then + BASEDIR="$BASEDIR$RCSUBDIR.$RCVERSION/" + fi fi SIGNATUREFILE="$BASEDIR$SIGNATUREFILENAME" @@ -92,12 +115,22 @@ if [ $RET -ne 0 ]; then exit "$RET" fi +if [ -n "$PLATFORM" ]; then + grep $PLATFORM $TMPFILE > "$TMPFILE-plat" + TMPFILESIZE=$(stat -c%s "$TMPFILE-plat") + if [ $TMPFILESIZE -eq 0 ]; then + echo "error: no files matched the platform specified" && exit 3 + fi + mv "$TMPFILE-plat" $TMPFILE +fi + #here we extract the filenames from the signature file FILES=$(awk '{print $2}' "$TMPFILE") #and download these one by one for file in $FILES do + echo "Downloading $file" wget --quiet -N "$BASEDIR$file" done From 305fd06796c5c17185586ecad5c87c3a0d060abe Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 Jun 2017 19:40:00 +0200 Subject: [PATCH 405/987] Merge #10248: Rewrite addrdb with less duplication using CHashVerifier cf68a48 Deduplicate addrdb.cpp and use CHashWriter/Verifier (Pieter Wuille) Tree-SHA512: 0301332e797f64da3a1588c9ebaf533af58da41e38f8a64206bff20102c5e82c2a7c630ca3150cf451b2ccf4acb3dd45e44259b6ba15e92786e9e9a2b225bd2f --- src/addrdb.cpp | 214 ++++++++++++++++--------------------------------- src/addrdb.h | 2 +- 2 files changed, 72 insertions(+), 144 deletions(-) diff --git a/src/addrdb.cpp b/src/addrdb.cpp index dce52aea6ae6..5239e893844f 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -15,25 +15,31 @@ #include "tinyformat.h" #include "util.h" +namespace { -CBanDB::CBanDB() +template +bool SerializeDB(Stream& stream, const Data& data) { - pathBanlist = GetDataDir() / "banlist.dat"; + // Write and commit header, data + try { + CHashWriter hasher(SER_DISK, CLIENT_VERSION); + stream << FLATDATA(Params().MessageStart()) << data; + hasher << FLATDATA(Params().MessageStart()) << data; + stream << hasher.GetHash(); + } catch (const std::exception& e) { + return error("%s: Serialize or I/O error - %s", __func__, e.what()); + } + + return true; } -bool CBanDB::Write(const banmap_t& banSet) +template +bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data) { // Generate random temporary filename unsigned short randv = 0; GetRandBytes((unsigned char*)&randv, sizeof(randv)); - std::string tmpfn = strprintf("banlist.dat.%04x", randv); - - // serialize banlist, checksum data up to that point, then append csum - CDataStream ssBanlist(SER_DISK, CLIENT_VERSION); - ssBanlist << FLATDATA(Params().MessageStart()); - ssBanlist << banSet; - uint256 hash = Hash(ssBanlist.begin(), ssBanlist.end()); - ssBanlist << hash; + std::string tmpfn = strprintf("%s.%04x", prefix, randv); // open temp output file, and associate with CAutoFile fs::path pathTmp = GetDataDir() / tmpfn; @@ -42,69 +48,41 @@ bool CBanDB::Write(const banmap_t& banSet) if (fileout.IsNull()) return error("%s: Failed to open file %s", __func__, pathTmp.string()); - // Write and commit header, data - try { - fileout << ssBanlist; - } - catch (const std::exception& e) { - return error("%s: Serialize or I/O error - %s", __func__, e.what()); - } + // Serialize + if (!SerializeDB(fileout, data)) return false; FileCommit(fileout.Get()); fileout.fclose(); - // replace existing banlist.dat, if any, with new banlist.dat.XXXX - if (!RenameOver(pathTmp, pathBanlist)) + // replace existing file, if any, with new file + if (!RenameOver(pathTmp, path)) return error("%s: Rename-into-place failed", __func__); return true; } -bool CBanDB::Read(banmap_t& banSet) +template +bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true) { - // open input file, and associate with CAutoFile - FILE *file = fsbridge::fopen(pathBanlist, "rb"); - CAutoFile filein(file, SER_DISK, CLIENT_VERSION); - if (filein.IsNull()) - return error("%s: Failed to open file %s", __func__, pathBanlist.string()); - - // use file size to size memory buffer - uint64_t fileSize = fs::file_size(pathBanlist); - uint64_t dataSize = 0; - // Don't try to resize to a negative number if file is small - if (fileSize >= sizeof(uint256)) - dataSize = fileSize - sizeof(uint256); - std::vector vchData; - vchData.resize(dataSize); - uint256 hashIn; - - // read data and checksum from file - try { - filein.read((char *)&vchData[0], dataSize); - filein >> hashIn; - } - catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); - } - filein.fclose(); - - CDataStream ssBanlist(vchData, SER_DISK, CLIENT_VERSION); - - // verify stored checksum matches input data - uint256 hashTmp = Hash(ssBanlist.begin(), ssBanlist.end()); - if (hashIn != hashTmp) - return error("%s: Checksum mismatch, data corrupted", __func__); - - unsigned char pchMsgTmp[4]; try { + CHashVerifier verifier(&stream); // de-serialize file header (network specific magic number) and .. - ssBanlist >> FLATDATA(pchMsgTmp); - + unsigned char pchMsgTmp[4]; + verifier >> FLATDATA(pchMsgTmp); // ... verify the network matches ours if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) return error("%s: Invalid network magic number", __func__); - // de-serialize ban data - ssBanlist >> banSet; + // de-serialize data + verifier >> data; + + // verify checksum + if (fCheckSum) { + uint256 hashTmp; + stream >> hashTmp; + if (hashTmp != verifier.GetHash()) { + return error("%s: Checksum mismatch, data corrupted", __func__); + } + } } catch (const std::exception& e) { return error("%s: Deserialize or I/O error - %s", __func__, e.what()); @@ -113,106 +91,56 @@ bool CBanDB::Read(banmap_t& banSet) return true; } -CAddrDB::CAddrDB() +template +bool DeserializeFileDB(const fs::path& path, Data& data) { - pathAddr = GetDataDir() / "peers.dat"; + // open input file, and associate with CAutoFile + FILE *file = fsbridge::fopen(path, "rb"); + CAutoFile filein(file, SER_DISK, CLIENT_VERSION); + if (filein.IsNull()) + return error("%s: Failed to open file %s", __func__, path.string()); + + return DeserializeDB(filein, data); } -bool CAddrDB::Write(const CAddrMan& addr) -{ - // Generate random temporary filename - unsigned short randv = 0; - GetRandBytes((unsigned char*)&randv, sizeof(randv)); - std::string tmpfn = strprintf("peers.dat.%04x", randv); +} - // serialize addresses, checksum data up to that point, then append csum - CDataStream ssPeers(SER_DISK, CLIENT_VERSION); - ssPeers << FLATDATA(Params().MessageStart()); - ssPeers << addr; - uint256 hash = Hash(ssPeers.begin(), ssPeers.end()); - ssPeers << hash; +CBanDB::CBanDB() +{ + pathBanlist = GetDataDir() / "banlist.dat"; +} - // open temp output file, and associate with CAutoFile - fs::path pathTmp = GetDataDir() / tmpfn; - FILE *file = fsbridge::fopen(pathTmp, "wb"); - CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); - if (fileout.IsNull()) - return error("%s: Failed to open file %s", __func__, pathTmp.string()); +bool CBanDB::Write(const banmap_t& banSet) +{ + return SerializeFileDB("banlist", pathBanlist, banSet); +} - // Write and commit header, data - try { - fileout << ssPeers; - } - catch (const std::exception& e) { - return error("%s: Serialize or I/O error - %s", __func__, e.what()); - } - FileCommit(fileout.Get()); - fileout.fclose(); +bool CBanDB::Read(banmap_t& banSet) +{ + return DeserializeFileDB(pathBanlist, banSet); +} - // replace existing peers.dat, if any, with new peers.dat.XXXX - if (!RenameOver(pathTmp, pathAddr)) - return error("%s: Rename-into-place failed", __func__); +CAddrDB::CAddrDB() +{ + pathAddr = GetDataDir() / "peers.dat"; +} - return true; +bool CAddrDB::Write(const CAddrMan& addr) +{ + return SerializeFileDB("peers", pathAddr, addr); } bool CAddrDB::Read(CAddrMan& addr) { - // open input file, and associate with CAutoFile - FILE *file = fsbridge::fopen(pathAddr, "rb"); - CAutoFile filein(file, SER_DISK, CLIENT_VERSION); - if (filein.IsNull()) - return error("%s: Failed to open file %s", __func__, pathAddr.string()); - - // use file size to size memory buffer - uint64_t fileSize = fs::file_size(pathAddr); - uint64_t dataSize = 0; - // Don't try to resize to a negative number if file is small - if (fileSize >= sizeof(uint256)) - dataSize = fileSize - sizeof(uint256); - std::vector vchData; - vchData.resize(dataSize); - uint256 hashIn; - - // read data and checksum from file - try { - filein.read((char *)&vchData[0], dataSize); - filein >> hashIn; - } - catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); - } - filein.fclose(); - - CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); - - // verify stored checksum matches input data - uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); - if (hashIn != hashTmp) - return error("%s: Checksum mismatch, data corrupted", __func__); - - return Read(addr, ssPeers); + return DeserializeFileDB(pathAddr, addr); } bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers) { - unsigned char pchMsgTmp[4]; - try { - // de-serialize file header (network specific magic number) and .. - ssPeers >> FLATDATA(pchMsgTmp); - - // ... verify the network matches ours - if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) - return error("%s: Invalid network magic number", __func__); - - // de-serialize address data into one CAddrMan object - ssPeers >> addr; - } - catch (const std::exception& e) { - // de-serialization has failed, ensure addrman is left in a clean state + bool ret = DeserializeDB(ssPeers, addr, false); + if (!ret) { + // Ensure addrman is left in a clean state addr.Clear(); - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); } - - return true; + return ret; } diff --git a/src/addrdb.h b/src/addrdb.h index afb62c580ad2..4e3b45c3f095 100644 --- a/src/addrdb.h +++ b/src/addrdb.h @@ -85,7 +85,7 @@ class CAddrDB CAddrDB(); bool Write(const CAddrMan& addr); bool Read(CAddrMan& addr); - bool Read(CAddrMan& addr, CDataStream& ssPeers); + static bool Read(CAddrMan& addr, CDataStream& ssPeers); }; /** Access to the banlist database (banlist.dat) */ From 5f2c9d7307c52dfecf4a9cfa5a6425f1eb04979a Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 22 Jun 2017 20:36:16 +0200 Subject: [PATCH 406/987] Merge #10633: doc: Fix various typos 0a5a6b9 Fixed multiple typos (Dimitris Tsapakidis) Tree-SHA512: 57748710bcbc03945b160db5e95bd686a2c64605f25d5e11d8ed9d0e1be3b3bf287a63588dc6eb33d0cef4ff17c765fda7c226d667a357acc539c8fcf2b9bb7e --- doc/developer-notes.md | 2 +- src/chain.cpp | 2 +- src/cuckoocache.h | 4 ++-- src/httpserver.h | 4 ++-- src/leveldb/db/version_set.h | 2 +- src/qt/clientmodel.cpp | 2 +- src/qt/forms/optionsdialog.ui | 6 +++--- src/qt/modaloverlay.cpp | 2 +- src/qt/rpcconsole.cpp | 4 ++-- src/qt/walletmodel.cpp | 2 +- src/rest.cpp | 2 +- src/rpc/net.cpp | 16 ++++++++-------- src/secp256k1/sage/group_prover.sage | 2 +- src/secp256k1/src/asm/field_10x26_arm.s | 2 +- src/test/arith_uint256_tests.cpp | 2 +- src/test/data/script_tests.json | 4 ++-- src/test/data/tx_valid.json | 2 +- src/torcontrol.cpp | 2 +- src/txmempool.cpp | 2 +- src/utilstrencodings.cpp | 8 ++++---- src/validation.cpp | 2 +- src/wallet/rpcdump.cpp | 2 +- src/wallet/wallet.cpp | 6 +++--- test/functional/pruning.py | 2 +- test/functional/rest.py | 22 +++++++++++----------- test/functional/smartfees.py | 2 +- test/functional/test_framework/mininode.py | 2 +- test/functional/zapwallettxes.py | 2 +- 28 files changed, 56 insertions(+), 56 deletions(-) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index d0f6e2773ea0..4a942f9655f1 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -267,7 +267,7 @@ General C++ - Assertions should not have side-effects - - *Rationale*: Even though the source code is set to to refuse to compile + - *Rationale*: Even though the source code is set to refuse to compile with assertions disabled, having side-effects in assertions is unexpected and makes the code harder to understand diff --git a/src/chain.cpp b/src/chain.cpp index 6154e24f2317..e075e36c83cc 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -126,7 +126,7 @@ arith_uint256 GetBlockProof(const CBlockIndex& block) if (fNegative || fOverflow || bnTarget == 0) return 0; // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 - // as it's too large for a arith_uint256. However, as 2**256 is at least as large + // as it's too large for an arith_uint256. However, as 2**256 is at least as large // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1, // or ~bnTarget / (nTarget+1) + 1. return (~bnTarget / (bnTarget + 1)) + 1; diff --git a/src/cuckoocache.h b/src/cuckoocache.h index 58375494555e..2e66901b3504 100644 --- a/src/cuckoocache.h +++ b/src/cuckoocache.h @@ -176,7 +176,7 @@ class cache */ mutable std::vector epoch_flags; - /** epoch_heuristic_counter is used to determine when a epoch might be aged + /** epoch_heuristic_counter is used to determine when an epoch might be aged * & an expensive scan should be done. epoch_heuristic_counter is * decremented on insert and reset to the new number of inserts which would * cause the epoch to reach epoch_size when it reaches zero. @@ -184,7 +184,7 @@ class cache uint32_t epoch_heuristic_counter; /** epoch_size is set to be the number of elements supposed to be in a - * epoch. When the number of non-erased elements in a epoch + * epoch. When the number of non-erased elements in an epoch * exceeds epoch_size, a new epoch should be started and all * current entries demoted. epoch_size is set to be 45% of size because * we want to keep load around 90%, and we support 3 epochs at once -- diff --git a/src/httpserver.h b/src/httpserver.h index d9b45f076d64..b7fce073208b 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -86,7 +86,7 @@ class HTTPRequest /** * Get the request header specified by hdr, or an empty string. - * Return an pair (isPresent,string). + * Return a pair (isPresent,string). */ std::pair GetHeader(const std::string& hdr); @@ -125,7 +125,7 @@ class HTTPClosure virtual ~HTTPClosure() {} }; -/** Event class. This can be used either as an cross-thread trigger or as a timer. +/** Event class. This can be used either as a cross-thread trigger or as a timer. */ class HTTPEvent { diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h index c4e7ac360b87..7935a965a7c9 100644 --- a/src/leveldb/db/version_set.h +++ b/src/leveldb/db/version_set.h @@ -376,7 +376,7 @@ class Compaction { // Each compaction reads inputs from "level_" and "level_+1" std::vector inputs_[2]; // The two sets of inputs - // State used to check for number of of overlapping grandparent files + // State used to check for number of overlapping grandparent files // (parent == level_ + 1, grandparent == level_ + 2) std::vector grandparents_; size_t grandparent_index_; // Index in grandparent_starts_ diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 1836509e13d3..70520446cf0f 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -340,7 +340,7 @@ static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CB } // if we are in-sync, update the UI regardless of last update time if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) { - //pass a async signal to the UI thread + //pass an async signal to the UI thread QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection, Q_ARG(int, pIndex->nHeight), Q_ARG(QDateTime, QDateTime::fromTime_t(pIndex->GetBlockTime())), diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index f0cf50166516..d2b12b9bf44e 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -434,7 +434,7 @@ false - Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. @@ -457,7 +457,7 @@ false - Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. @@ -480,7 +480,7 @@ false - Shows, if the supplied default SOCKS5 proxy is used to reach peers via this network type. + Shows if the supplied default SOCKS5 proxy is used to reach peers via this network type. diff --git a/src/qt/modaloverlay.cpp b/src/qt/modaloverlay.cpp index d45320c5b5ab..bb72bdc4ea13 100644 --- a/src/qt/modaloverlay.cpp +++ b/src/qt/modaloverlay.cpp @@ -129,7 +129,7 @@ void ModalOverlay::tipUpdate(int count, const QDateTime& blockDate, double nVeri return; // estimate the number of headers left based on nPowTargetSpacing - // and check if the gui is not aware of the the best header (happens rarely) + // and check if the gui is not aware of the best header (happens rarely) int estimateNumHeadersLeft = bestHeaderDate.secsTo(currentDate) / Params().GetConsensus().nPowTargetSpacing; bool hasBestHeader = bestHeaderHeight >= count; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index f174c2b04b3e..0a17126766a5 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -702,7 +702,7 @@ void RPCConsole::setFontSize(int newSize) { QSettings settings; - //don't allow a insane font size + //don't allow an insane font size if (newSize < FONT_RANGE.width() || newSize > FONT_RANGE.height()) return; @@ -830,7 +830,7 @@ void RPCConsole::clear(bool clearHistory) tr("Use up and down arrows to navigate history, and %1 to clear screen.").arg(""+clsKey+"") + "
    " + tr("Type help for an overview of available commands.")) + "
    " + - tr("WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramification of a command.") + + tr("WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.") + "", true); } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 4d2ef994ad26..af6823116b28 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -398,7 +398,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran transaction_array.append(&(ssTx[0]), ssTx.size()); } - // Add addresses / update labels that we've sent to to the address book, + // Add addresses / update labels that we've sent to the address book, // and emit coinsSent signal for each recipient for (const SendCoinsRecipient &rcp : transaction.getRecipients()) { diff --git a/src/rest.cpp b/src/rest.cpp index 69220579269d..0c0551cfe691 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -413,7 +413,7 @@ static bool rest_getutxos(HTTPRequest* req, const std::string& strURIPart) boost::split(uriParts, strUriParams, boost::is_any_of("/")); } - // throw exception in case of a empty request + // throw exception in case of an empty request std::string strRequestMutable = req->ReadBody(); if (strRequestMutable.length() == 0 && uriParts.size() == 0) return RESTERR(req, HTTP_BAD_REQUEST, "Error: empty request"); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 5396e548c97d..34fc8d79e0d7 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -76,7 +76,7 @@ UniValue getpeerinfo(const JSONRPCRequest& request) "[\n" " {\n" " \"id\": n, (numeric) Peer index\n" - " \"addr\":\"host:port\", (string) The ip address and port of the peer\n" + " \"addr\":\"host:port\", (string) The IP address and port of the peer\n" " \"addrbind\":\"ip:port\", (string) Bind address of the connection to the peer\n" " \"addrlocal\":\"ip:port\", (string) Local address as reported by the peer\n" " \"services\":\"xxxxxxxxxxxxxxxx\", (string) The services offered\n" @@ -200,7 +200,7 @@ UniValue addnode(const JSONRPCRequest& request) (strCommand != "onetry" && strCommand != "add" && strCommand != "remove")) throw std::runtime_error( "addnode \"node\" \"add|remove|onetry\"\n" - "\nAttempts add or remove a node from the addnode list.\n" + "\nAttempts to add or remove a node from the addnode list.\n" "Or try a connection to a node once.\n" "\nArguments:\n" "1. \"node\" (string, required) The node (see getpeerinfo for nodes)\n" @@ -291,7 +291,7 @@ UniValue getaddednodeinfo(const JSONRPCRequest& request) "\nResult:\n" "[\n" " {\n" - " \"addednode\" : \"192.168.0.201\", (string) The node ip address or name (as provided to addnode)\n" + " \"addednode\" : \"192.168.0.201\", (string) The node IP address or name (as provided to addnode)\n" " \"connected\" : true|false, (boolean) If connected\n" " \"addresses\" : [ (list of objects) Only when connected = true\n" " {\n" @@ -498,12 +498,12 @@ UniValue setban(const JSONRPCRequest& request) (strCommand != "add" && strCommand != "remove")) throw std::runtime_error( "setban \"subnet\" \"add|remove\" (bantime) (absolute)\n" - "\nAttempts add or remove a IP/Subnet from the banned list.\n" + "\nAttempts to add or remove an IP/Subnet from the banned list.\n" "\nArguments:\n" - "1. \"subnet\" (string, required) The IP/Subnet (see getpeerinfo for nodes ip) with a optional netmask (default is /32 = single ip)\n" - "2. \"command\" (string, required) 'add' to add a IP/Subnet to the list, 'remove' to remove a IP/Subnet from the list\n" - "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the ip is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" - "4. \"absolute\" (boolean, optional) If set, the bantime must be a absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n" + "1. \"subnet\" (string, required) The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)\n" + "2. \"command\" (string, required) 'add' to add an IP/Subnet to the list, 'remove' to remove an IP/Subnet from the list\n" + "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the IP is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" + "4. \"absolute\" (boolean, optional) If set, the bantime must be an absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n" "\nExamples:\n" + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") diff --git a/src/secp256k1/sage/group_prover.sage b/src/secp256k1/sage/group_prover.sage index ab580c5b23bb..5198724bea15 100644 --- a/src/secp256k1/sage/group_prover.sage +++ b/src/secp256k1/sage/group_prover.sage @@ -3,7 +3,7 @@ # to independently set assumptions on input or intermediary variables. # # The general approach is: -# * A constraint is a tuple of two sets of of symbolic expressions: +# * A constraint is a tuple of two sets of symbolic expressions: # the first of which are required to evaluate to zero, the second of which # are required to evaluate to nonzero. # - A constraint is said to be conflicting if any of its nonzero expressions diff --git a/src/secp256k1/src/asm/field_10x26_arm.s b/src/secp256k1/src/asm/field_10x26_arm.s index 5df561f2fc93..bd2b629e1c2e 100644 --- a/src/secp256k1/src/asm/field_10x26_arm.s +++ b/src/secp256k1/src/asm/field_10x26_arm.s @@ -11,7 +11,7 @@ Note: - To avoid unnecessary loads and make use of available registers, two 'passes' have every time been interleaved, with the odd passes accumulating c' and d' - which will be added to c and d respectively in the the even passes + which will be added to c and d respectively in the even passes */ diff --git a/src/test/arith_uint256_tests.cpp b/src/test/arith_uint256_tests.cpp index 20cccdc2abc7..4452fb76a316 100644 --- a/src/test/arith_uint256_tests.cpp +++ b/src/test/arith_uint256_tests.cpp @@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE( unaryOperators ) // ! ~ - // Check if doing _A_ _OP_ _B_ results in the same as applying _OP_ onto each -// element of Aarray and Barray, and then converting the result into a arith_uint256. +// element of Aarray and Barray, and then converting the result into an arith_uint256. #define CHECKBITWISEOPERATOR(_A_,_B_,_OP_) \ for (unsigned int i = 0; i < 32; ++i) { TmpArray[i] = _A_##Array[i] _OP_ _B_##Array[i]; } \ BOOST_CHECK(arith_uint256V(std::vector(TmpArray,TmpArray+32)) == (_A_##L _OP_ _B_##L)); diff --git a/src/test/data/script_tests.json b/src/test/data/script_tests.json index 3631ce3d5d86..ec2afb84c3cc 100644 --- a/src/test/data/script_tests.json +++ b/src/test/data/script_tests.json @@ -1850,8 +1850,8 @@ "P2SH with CLEANSTACK" ], -["CHECKSEQUENCEVERIFY tests"], -["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on a empty stack"], +["CHECKSEQUENCEVERIFY tests"], +["", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "INVALID_STACK_OPERATION", "CSV automatically fails on an empty stack"], ["-1", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "NEGATIVE_LOCKTIME", "CSV automatically fails if stack top is negative"], ["0x0100", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY,MINIMALDATA", "UNKNOWN_ERROR", "CSV fails if stack top is not minimally encoded"], ["0", "CHECKSEQUENCEVERIFY", "CHECKSEQUENCEVERIFY", "UNSATISFIED_LOCKTIME", "CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json index aa0aadeac3d4..06190df3261b 100644 --- a/src/test/data/tx_valid.json +++ b/src/test/data/tx_valid.json @@ -174,7 +174,7 @@ [[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], "01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"], -["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."], +["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."], ["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"], [[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp index 3f460ae8c71e..0f6e11a2eab3 100644 --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -407,7 +407,7 @@ static bool WriteBinaryFile(const fs::path &filename, const std::string &data) /****** Bitcoin specific TorController implementation ********/ /** Controller that connects to Tor control socket, authenticate, then create - * and maintain a ephemeral hidden service. + * and maintain an ephemeral hidden service. */ class TorController { diff --git a/src/txmempool.cpp b/src/txmempool.cpp index e5c8c5664ac3..124666efe8cf 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -123,7 +123,7 @@ void CTxMemPool::UpdateTransactionsFromBlock(const std::vector &vHashes // accounted for in the state of their ancestors) std::set setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end()); - // Iterate in reverse, so that whenever we are looking at at a transaction + // Iterate in reverse, so that whenever we are looking at a transaction // we are sure that all in-mempool descendants have already been processed. // This maximizes the benefit of the descendant cache and guarantees that // setMemPoolChildren will be updated, an assumption made in diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index bbaecbf5cef9..339f805b794f 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -437,7 +437,7 @@ bool ParseInt32(const std::string& str, int32_t *out) errno = 0; // strtol will not set errno if valid long int n = strtol(str.c_str(), &endp, 10); if(out) *out = (int32_t)n; - // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow + // Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit // platforms the size of these types may be different. return endp && *endp == 0 && !errno && @@ -453,7 +453,7 @@ bool ParseInt64(const std::string& str, int64_t *out) errno = 0; // strtoll will not set errno if valid long long int n = strtoll(str.c_str(), &endp, 10); if(out) *out = (int64_t)n; - // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow + // Note that strtoll returns a *long long int*, so even if strtol doesn't report an over/underflow // we still have to check that the returned value is within the range of an *int64_t*. return endp && *endp == 0 && !errno && n >= std::numeric_limits::min() && @@ -470,7 +470,7 @@ bool ParseUInt32(const std::string& str, uint32_t *out) errno = 0; // strtoul will not set errno if valid unsigned long int n = strtoul(str.c_str(), &endp, 10); if(out) *out = (uint32_t)n; - // Note that strtoul returns a *unsigned long int*, so even if it doesn't report a over/underflow + // Note that strtoul returns a *unsigned long int*, so even if it doesn't report an over/underflow // we still have to check that the returned value is within the range of an *uint32_t*. On 64-bit // platforms the size of these types may be different. return endp && *endp == 0 && !errno && @@ -487,7 +487,7 @@ bool ParseUInt64(const std::string& str, uint64_t *out) errno = 0; // strtoull will not set errno if valid unsigned long long int n = strtoull(str.c_str(), &endp, 10); if(out) *out = (uint64_t)n; - // Note that strtoull returns a *unsigned long long int*, so even if it doesn't report a over/underflow + // Note that strtoull returns a *unsigned long long int*, so even if it doesn't report an over/underflow // we still have to check that the returned value is within the range of an *uint64_t*. return endp && *endp == 0 && !errno && n <= std::numeric_limits::max(); diff --git a/src/validation.cpp b/src/validation.cpp index 6f96fb56894e..609b551cd53e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1488,7 +1488,7 @@ static bool CheckInputs(const CTransaction& tx, CValidationState &state, const C return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError()))); } // Failures of other flags indicate a transaction that is - // invalid in new blocks, e.g. a invalid P2SH. We DoS ban + // invalid in new blocks, e.g. an invalid P2SH. We DoS ban // such nodes as they are not following the protocol. That // said during an upgrade careful thought should be taken // as to the correct behavior - we may want to continue diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 05af581dc032..a8dc7a7a2f01 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -1255,7 +1255,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest) " \"redeemscript\": \"