Skip to content

Commit cbbe801

Browse files
Merge pull request dashpay#4675 from Munkybooty/backports-0.18-pr20
Backports 0.18 pr20
2 parents 515011a + ec162d7 commit cbbe801

13 files changed

Lines changed: 488 additions & 266 deletions

doc/release-notes-pr13381.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
RPC importprivkey: new label behavior
2+
-------------------------------------
3+
4+
Previously, `importprivkey` automatically added the default empty label
5+
("") to all addresses associated with the imported private key. Now it
6+
defaults to using any existing label for those addresses. For example:
7+
8+
- Old behavior: you import a watch-only address with the label "cold
9+
wallet". Later, you import the corresponding private key using the
10+
default settings. The address's label is changed from "cold wallet"
11+
to "".
12+
13+
- New behavior: you import a watch-only address with the label "cold
14+
wallet". Later, you import the corresponding private key using the
15+
default settings. The address's label remains "cold wallet".
16+
17+
In both the previous and current case, if you directly specify a label
18+
during the import, that label will override whatever previous label the
19+
addresses may have had. Also in both cases, if none of the addresses
20+
previously had a label, they will still receive the default empty label
21+
(""). Examples:
22+
23+
- You import a watch-only address with the label "temporary". Later you
24+
import the corresponding private key with the label "final". The
25+
address's label will be changed to "final".
26+
27+
- You use the default settings to import a private key for an address that
28+
was not previously in the wallet. Its addresses will receive the default
29+
empty label ("").

src/chainparams.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,10 +814,10 @@ class CRegTestParams : public CChainParams {
814814
consensus.nGovernanceMinQuorum = 1;
815815
consensus.nGovernanceFilterElements = 100;
816816
consensus.nMasternodeMinimumConfirmations = 1;
817-
consensus.BIP34Height = 100000000; // BIP34 has not activated on regtest (far in the future so block v1 are not rejected in tests)
817+
consensus.BIP34Height = 500; // BIP34 activated on regtest (Used in functional tests)
818818
consensus.BIP34Hash = uint256();
819-
consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in rpc activation tests)
820-
consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in rpc activation tests)
819+
consensus.BIP65Height = 1351; // BIP65 activated on regtest (Used in functional tests)
820+
consensus.BIP66Height = 1251; // BIP66 activated on regtest (Used in functional tests)
821821
consensus.DIP0001Height = 2000;
822822
consensus.DIP0003Height = 432;
823823
consensus.DIP0003EnforcementHeight = 500;

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1856,7 +1856,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
18561856
if (request.fHelp || request.params.size() != 1)
18571857
throw std::runtime_error(
18581858
RPCHelpMan{"reconsiderblock",
1859-
"\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
1859+
"\nRemoves invalidity status of a block, its ancestors and its descendants, reconsider them for activation.\n"
18601860
"This can be used to undo the effects of invalidateblock.\n",
18611861
{
18621862
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "the hash of the block to reconsider"},

src/rpc/server.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2010 Satoshi Nakamoto
2-
// Copyright (c) 2009-2018 The Bitcoin Core developers
2+
// Copyright (c) 2009-2019 The Bitcoin Core developers
33
// Copyright (c) 2014-2021 The Dash Core developers
44
// Distributed under the MIT software license, see the accompanying
55
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -54,7 +54,7 @@ struct RPCCommandExecution
5454
explicit RPCCommandExecution(const std::string& method)
5555
{
5656
LOCK(g_rpc_server_info.mutex);
57-
it = g_rpc_server_info.active_commands.insert(g_rpc_server_info.active_commands.cend(), {method, GetTimeMicros()});
57+
it = g_rpc_server_info.active_commands.insert(g_rpc_server_info.active_commands.end(), {method, GetTimeMicros()});
5858
}
5959
~RPCCommandExecution()
6060
{

src/wallet/rpcdump.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ UniValue importprivkey(const JSONRPCRequest& request)
157157
CKeyID vchAddress = pubkey.GetID();
158158
{
159159
pwallet->MarkDirty();
160-
pwallet->SetAddressBook(vchAddress, strLabel, "receive");
160+
161+
if (!request.params[1].isNull() || pwallet->mapAddressBook.count(vchAddress) == 0) {
162+
pwallet->SetAddressBook(vchAddress, strLabel, "receive");
163+
}
161164

162165
// Don't throw error in case a key is already there
163166
if (pwallet->HaveKey(vchAddress)) {
@@ -1493,7 +1496,9 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
14931496
if (mainRequest.fHelp || mainRequest.params.size() < 1 || mainRequest.params.size() > 2)
14941497
throw std::runtime_error(
14951498
RPCHelpMan{"importmulti",
1496-
"\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options). Requires a new wallet backup.\n"
1499+
"\nImport addresses/scripts (with private or public keys, redeem script (P2SH)), optionally rescanning the blockchain from the earliest creation time of the imported scripts. Requires a new wallet backup.\n"
1500+
"If an address/script is imported without all of the private keys required to spend from that address, it will be watchonly. The 'watchonly' option must be set to true in this case or a warning will be returned.\n"
1501+
"Conversely, if all the private keys are provided and the address/script is spendable, the watchonly option must be set to false, or a warning will be returned.\n"
14971502
"\nNote: This call can take over an hour to complete if rescan is true, during that time, other rpc calls\n"
14981503
"may report that the imported keys, addresses or scripts exists but related transactions are still missing.\n",
14991504
{
@@ -1527,7 +1532,7 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
15271532
},
15281533
{"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED, "If a ranged descriptor is used, this specifies the end or the range (in the form [begin,end]) to import"},
15291534
{"internal", RPCArg::Type::BOOL, /* default */ "false", "Stating whether matching outputs should be treated as not incoming payments (also known as change)"},
1530-
{"watchonly", RPCArg::Type::BOOL, /* default */ "false", "Stating whether matching outputs should be considered watched even when not all private keys are provided."},
1535+
{"watchonly", RPCArg::Type::BOOL, /* default */ "false", "Stating whether matching outputs should be considered watchonly."},
15311536
{"label", RPCArg::Type::STR, /* default */ "''", "Label to assign to the address, only allowed with internal=false"},
15321537
{"keypool", RPCArg::Type::BOOL, /* default */ "false", "Stating whether imported public keys should be added to the keypool for when users request new addresses. Only allowed when wallet private keys are disabled"},
15331538
},

src/wallet/rpcwallet.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3719,8 +3719,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
37193719
" ,...\n"
37203720
" ]\n"
37213721
" \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n"
3722-
" \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH)\n"
3723-
" \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\") and relation to the wallet (\"ismine\", \"iswatchonly\").\n"
3722+
" \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses\n"
37243723
" \"iscompressed\" : true|false, (boolean, optional) If the pubkey is compressed\n"
37253724
" \"label\" : \"label\" (string) The label associated with the address, \"\" is the default label\n"
37263725
" \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n"
@@ -4023,7 +4022,7 @@ UniValue walletcreatefundedpsbt(const JSONRPCRequest& request)
40234022
return NullUniValue;
40244023
}
40254024

4026-
if (request.fHelp || request.params.size() < 2 || request.params.size() > 6)
4025+
if (request.fHelp || request.params.size() < 2 || request.params.size() > 5)
40274026
throw std::runtime_error(
40284027
RPCHelpMan{"walletcreatefundedpsbt",
40294028
"\nCreates and funds a transaction in the Partially Signed Transaction format. Inputs will be added if supplied inputs are not enough\n"

test/functional/feature_block.py

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,7 +1250,7 @@ def run_test(self):
12501250
blocks = []
12511251
spend = out[32]
12521252
for i in range(89, LARGE_REORG_SIZE + 89):
1253-
b = self.next_block(i, spend)
1253+
b = self.next_block(i, spend, version=4)
12541254
tx = CTransaction()
12551255
script_length = MAX_BLOCK_SIZE - len(b.serialize()) - 69
12561256
script_output = CScript([b'\x00' * script_length])
@@ -1269,20 +1269,32 @@ def run_test(self):
12691269
self.move_tip(88)
12701270
blocks2 = []
12711271
for i in range(89, LARGE_REORG_SIZE + 89):
1272-
blocks2.append(self.next_block("alt" + str(i)))
1272+
blocks2.append(self.next_block("alt" + str(i), version=4))
12731273
self.send_blocks(blocks2, False, force_send=True)
12741274

12751275
# extend alt chain to trigger re-org
1276-
block = self.next_block("alt" + str(chain1_tip + 1))
1276+
block = self.next_block("alt" + str(chain1_tip + 1), version=4)
12771277
self.send_blocks([block], True, timeout=960)
12781278

12791279
# ... and re-org back to the first chain
12801280
self.move_tip(chain1_tip)
1281-
block = self.next_block(chain1_tip + 1)
1281+
block = self.next_block(chain1_tip + 1, version=4)
12821282
self.send_blocks([block], False, force_send=True)
1283-
block = self.next_block(chain1_tip + 2)
1283+
block = self.next_block(chain1_tip + 2, version=4)
12841284
self.send_blocks([block], True, timeout=960)
12851285

1286+
self.log.info("Reject a block with an invalid block header version")
1287+
b_v1 = self.next_block('b_v1', version=1)
1288+
self.send_blocks([b_v1], success=False, force_send=True, reject_reason='bad-version(0x00000001)')
1289+
1290+
self.move_tip(chain1_tip + 2)
1291+
b_cb34 = self.next_block('b_cb34', version=4)
1292+
b_cb34.vtx[0].vin[0].scriptSig = b_cb34.vtx[0].vin[0].scriptSig[:-1]
1293+
b_cb34.vtx[0].rehash()
1294+
b_cb34.hashMerkleRoot = b_cb34.calc_merkle_root()
1295+
b_cb34.solve()
1296+
self.send_blocks([b_cb34], success=False, reject_reason='bad-cb-height', reconnect=True)
1297+
12861298
# Helper methods
12871299
################
12881300

@@ -1310,7 +1322,7 @@ def create_and_sign_transaction(self, spend_tx, value, script=CScript([OP_TRUE])
13101322
tx.rehash()
13111323
return tx
13121324

1313-
def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), solve=True):
1325+
def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), solve=True, *, version=1):
13141326
if self.tip is None:
13151327
base_block_hash = self.genesis_hash
13161328
block_time = self.mocktime + 1
@@ -1323,11 +1335,11 @@ def next_block(self, number, spend=None, additional_coinbase_value=0, script=CSc
13231335
coinbase.vout[0].nValue += additional_coinbase_value
13241336
coinbase.rehash()
13251337
if spend is None:
1326-
block = create_block(base_block_hash, coinbase, block_time)
1338+
block = create_block(base_block_hash, coinbase, block_time, version=version)
13271339
else:
13281340
coinbase.vout[0].nValue += spend.vout[0].nValue - 1 # all but one satoshi to fees
13291341
coinbase.rehash()
1330-
block = create_block(base_block_hash, coinbase, block_time)
1342+
block = create_block(base_block_hash, coinbase, block_time, version=version)
13311343
tx = self.create_tx(spend, 0, 1, script) # spend 1 satoshi
13321344
self.sign_tx(tx, spend)
13331345
self.add_transactions_to_block(block, [tx])

test/functional/rpc_invalidateblock.py

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
"""Test the invalidateblock RPC."""
66

7-
import time
8-
97
from test_framework.test_framework import BitcoinTestFramework
10-
from test_framework.util import assert_equal, connect_nodes, wait_until
8+
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
9+
from test_framework.util import (
10+
assert_equal,
11+
connect_nodes,
12+
wait_until,
13+
)
14+
1115

1216
class InvalidateTest(BitcoinTestFramework):
1317
def set_test_params(self):
@@ -21,46 +25,41 @@ def run_test(self):
2125
self.log.info("Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:")
2226
self.log.info("Mine 4 blocks on Node 0")
2327
self.nodes[0].generatetoaddress(4, self.nodes[0].get_deterministic_priv_key().address)
24-
assert self.nodes[0].getblockcount() == 4
25-
besthash = self.nodes[0].getbestblockhash()
28+
assert_equal(self.nodes[0].getblockcount(), 4)
29+
besthash_n0 = self.nodes[0].getbestblockhash()
2630

2731
self.log.info("Mine competing 6 blocks on Node 1")
2832
self.nodes[1].generatetoaddress(6, self.nodes[1].get_deterministic_priv_key().address)
29-
assert self.nodes[1].getblockcount() == 6
33+
assert_equal(self.nodes[1].getblockcount(), 6)
3034

3135
self.log.info("Connect nodes to force a reorg")
3236
connect_nodes(self.nodes[0], 1)
3337
self.sync_blocks(self.nodes[0:2])
34-
assert self.nodes[0].getblockcount() == 6
38+
assert_equal(self.nodes[0].getblockcount(), 6)
3539
badhash = self.nodes[1].getblockhash(2)
3640

3741
self.log.info("Invalidate block 2 on node 0 and verify we reorg to node 0's original chain")
3842
self.nodes[0].invalidateblock(badhash)
39-
newheight = self.nodes[0].getblockcount()
40-
newhash = self.nodes[0].getbestblockhash()
41-
if (newheight != 4 or newhash != besthash):
42-
raise AssertionError("Wrong tip for node0, hash %s, height %d"%(newhash,newheight))
43+
assert_equal(self.nodes[0].getblockcount(), 4)
44+
assert_equal(self.nodes[0].getbestblockhash(), besthash_n0)
4345

4446
self.log.info("Make sure we won't reorg to a lower work chain:")
45-
connect_nodes(self.nodes[1], 2)
47+
connect_nodes(self.nodes[ 1], 2)
4648
self.log.info("Sync node 2 to node 1 so both have 6 blocks")
4749
self.sync_blocks(self.nodes[1:3])
48-
assert self.nodes[2].getblockcount() == 6
50+
assert_equal(self.nodes[2].getblockcount(), 6)
4951
self.log.info("Invalidate block 5 on node 1 so its tip is now at 4")
5052
self.nodes[1].invalidateblock(self.nodes[1].getblockhash(5))
51-
assert self.nodes[1].getblockcount() == 4
53+
assert_equal(self.nodes[1].getblockcount(), 4)
5254
self.log.info("Invalidate block 3 on node 2, so its tip is now 2")
5355
self.nodes[2].invalidateblock(self.nodes[2].getblockhash(3))
54-
assert self.nodes[2].getblockcount() == 2
56+
assert_equal(self.nodes[2].getblockcount(), 2)
5557
self.log.info("..and then mine a block")
5658
self.nodes[2].generatetoaddress(1, self.nodes[2].get_deterministic_priv_key().address)
5759
self.log.info("Verify all nodes are at the right height")
58-
time.sleep(5)
59-
assert_equal(self.nodes[2].getblockcount(), 3)
60-
assert_equal(self.nodes[0].getblockcount(), 4)
61-
node1height = self.nodes[1].getblockcount()
62-
if node1height < 4:
63-
raise AssertionError("Node 1 reorged to a lower height: %d"%node1height)
60+
wait_until(lambda: self.nodes[2].getblockcount() == 3, timeout=5)
61+
wait_until(lambda: self.nodes[0].getblockcount() == 4, timeout=5)
62+
wait_until(lambda: self.nodes[1].getblockcount() == 4, timeout=5)
6463

6564
self.log.info("Make sure ResetBlockFailureFlags does the job correctly")
6665
self.restart_node(0, extra_args=["-checkblocks=5"])
@@ -88,6 +87,30 @@ def run_test(self):
8887
wait_until(lambda: self.nodes[1].getblockcount() == newheight + 20)
8988
assert_equal(tip, self.nodes[1].getbestblockhash())
9089

90+
self.log.info("Verify that we reconsider all ancestors as well")
91+
blocks = self.nodes[1].generatetoaddress(10, ADDRESS_BCRT1_UNSPENDABLE)
92+
assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
93+
# Invalidate the two blocks at the tip
94+
self.nodes[1].invalidateblock(blocks[-1])
95+
self.nodes[1].invalidateblock(blocks[-2])
96+
assert_equal(self.nodes[1].getbestblockhash(), blocks[-3])
97+
# Reconsider only the previous tip
98+
self.nodes[1].reconsiderblock(blocks[-1])
99+
# Should be back at the tip by now
100+
assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
101+
102+
self.log.info("Verify that we reconsider all descendants")
103+
blocks = self.nodes[1].generatetoaddress(10, ADDRESS_BCRT1_UNSPENDABLE)
104+
assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
105+
# Invalidate the two blocks at the tip
106+
self.nodes[1].invalidateblock(blocks[-2])
107+
self.nodes[1].invalidateblock(blocks[-4])
108+
assert_equal(self.nodes[1].getbestblockhash(), blocks[-5])
109+
# Reconsider only the previous tip
110+
self.nodes[1].reconsiderblock(blocks[-4])
111+
# Should be back at the tip by now
112+
assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
113+
91114

92115
if __name__ == '__main__':
93116
InvalidateTest().main()

test/functional/test_framework/blocktools.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@
2222
# Genesis block time (regtest)
2323
TIME_GENESIS_BLOCK = 1417713337
2424

25-
def create_block(hashprev, coinbase, ntime=None):
25+
def create_block(hashprev, coinbase, ntime=None, *, version=1):
2626
"""Create a block (with regtest difficulty)."""
2727
block = CBlock()
28+
block.nVersion = version
2829
if ntime is None:
2930
import time
3031
block.nTime = int(time.time() + 600)

0 commit comments

Comments
 (0)