aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/release-notes.md8
-rwxr-xr-xqa/rpc-tests/import-rescan.py30
-rw-r--r--src/init.cpp16
-rw-r--r--src/prevector.h6
-rw-r--r--src/wallet/test/wallet_tests.cpp2
5 files changed, 45 insertions, 17 deletions
diff --git a/doc/release-notes.md b/doc/release-notes.md
index 9c7064d0dc..0f2ed893fa 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -365,7 +365,6 @@ and git merge commit are mentioned.
- #8788 `97c7f73` Give RPC commands more information about the RPC request (jonasschnelli)
- #7948 `5d2c8e5` Augment getblockchaininfo bip9\_softforks data (mruddy)
- #8980 `0e22855` importmulti: Avoid using boost::variant::operator!=, which is only in newer boost versions (luke-jr)
-- #9087 `924de0b` Give more details when "generate" fails (jtimon)
- #9025 `4d8558a` Getrawtransaction should take a bool for verbose (jnewbery)
- #8811 `5754e03` Add support for JSON-RPC named arguments (laanwj)
- #9520 `2456a83` Deprecate non-txindex getrawtransaction and better warning (sipa)
@@ -425,7 +424,7 @@ and git merge commit are mentioned.
- #9349 `2db4cbc` Make CScript (and prevector) c++11 movable (sipa)
- #9252 `ce5c1f4` Release cs\_main before calling ProcessNewBlock, or processing headers (cmpctblock handling) (sdaftuar)
- #9283 `869781c` A few more CTransactionRef optimizations (sipa)
-- #9499 `9c9af5a` Use recent-rejects, orphans, and recently-replaced txn for compact-block-reconstruction
+- #9499 `9c9af5a` Use recent-rejects, orphans, and recently-replaced txn for compact-block-reconstruction (TheBlueMatt)
- #9813 `3972a8e` Read/write mempool.dat as a binary (paveljanik)
### P2P protocol and network code
@@ -572,7 +571,6 @@ and git merge commit are mentioned.
- #9817 `7d75a5a` Fix segfault crash when shutdown the GUI in disablewallet mode (jonasschnelli)
### Wallet
-- #8367 `045106b` Ensure <0.13 clients can't open HD wallets (jonasschnelli)
- #8152 `b9c1cd8` Remove `CWalletDB*` parameter from CWallet::AddToWallet (pstratem)
- #8432 `c7e05b3` Make CWallet::fFileBacked private (pstratem)
- #8445 `f916700` Move CWallet::setKeyPool to private section of CWallet (pstratem)
@@ -583,7 +581,7 @@ and git merge commit are mentioned.
- #8696 `a1f8d3e` Wallet: Remove last external reference to CWalletDB (pstratem)
- #8768 `886e8c9` init: Get rid of fDisableWallet (MarcoFalke)
- #8486 `ab0b411` Add high transaction fee warnings (MarcoFalke)
-- #8851 `940748b` Move key derivation logic from GenerateNewKey to DeriveNewChildKey (pstratem) (MarcoFalke)
+- #8851 `940748b` Move key derivation logic from GenerateNewKey to DeriveNewChildKey (pstratem)
- #8287 `e10af96` Set fLimitFree = true (MarcoFalke)
- #8928 `c587577` Fix init segfault where InitLoadWallet() calls ATMP before genesis (TheBlueMatt)
- #7551 `f2d7056` Add importmulti RPC call (pedrobranco)
@@ -662,7 +660,6 @@ and git merge commit are mentioned.
- #9691 `fc67cd2` Init ECC context for `test_bitcoin_fuzzy` (gmaxwell)
- #9712 `d304fef` bench: Fix initialization order in registration (laanwj)
- #9707 `b860915` Fix RPC failure testing (jnewbery)
-- #8621 `e8ed6eb` contrib: python: Don't use shell=True (MarcoFalke)
- #9269 `43e8150` Align struct COrphan definition (sipa)
- #9820 `599c69a` Fix pruning test broken by 2 hour manual prune window (ryanofsky)
- #9824 `260c71c` qa: Check return code when stopping nodes (MarcoFalke)
@@ -708,6 +705,7 @@ and git merge commit are mentioned.
- #8274 `7a2d402` util: Update tinyformat (laanwj)
- #8291 `5cac8b1` util: CopyrightHolders: Check for untranslated substitution (MarcoFalke)
- #8557 `44691f3` contrib: Rework verifybinaries (MarcoFalke)
+- #8621 `e8ed6eb` contrib: python: Don't use shell=True (MarcoFalke)
- #8813 `fb24d7e` bitcoind: Daemonize using daemon(3) (laanwj)
- #9004 `67728a3` Clarify `listenonion` (unsystemizer)
- #8674 `bae81b8` tools for analyzing, updating and adding copyright headers in source files (isle2983)
diff --git a/qa/rpc-tests/import-rescan.py b/qa/rpc-tests/import-rescan.py
index 54cc6d2642..7f2c321746 100755
--- a/qa/rpc-tests/import-rescan.py
+++ b/qa/rpc-tests/import-rescan.py
@@ -5,11 +5,11 @@
"""Test rescan behavior of importaddress, importpubkey, importprivkey, and
importmulti RPCs with different types of keys and rescan options.
-In the first part of the test, node 0 creates an address for each type of
-import RPC call and sends BTC to it. Then other nodes import the addresses,
-and the test makes listtransactions and getbalance calls to confirm that the
-importing node either did or did not execute rescans picking up the send
-transactions.
+In the first part of the test, node 1 creates an address for each type of
+import RPC call and node 0 sends BTC to it. Then other nodes import the
+addresses, and the test makes listtransactions and getbalance calls to confirm
+that the importing node either did or did not execute rescans picking up the
+send transactions.
In the second part of the test, node 0 sends more BTC to each address, and the
test makes more listtransactions and getbalance calls to confirm that the
@@ -81,6 +81,12 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
assert_equal(tx["txid"], txid)
assert_equal(tx["confirmations"], confirmations)
assert_equal("trusted" not in tx, True)
+ # Verify the transaction is correctly marked watchonly depending on
+ # whether the transaction pays to an imported public key or
+ # imported private key. The test setup ensures that transaction
+ # inputs will not be from watchonly keys (important because
+ # involvesWatchonly will be true if either the transaction output
+ # or inputs are watchonly).
if self.data != Data.priv:
assert_equal(tx["involvesWatchonly"], True)
else:
@@ -106,11 +112,11 @@ RESCAN_WINDOW = 2 * 60 * 60
class ImportRescanTest(BitcoinTestFramework):
def __init__(self):
super().__init__()
- self.num_nodes = 1 + len(IMPORT_NODES)
+ self.num_nodes = 2 + len(IMPORT_NODES)
def setup_network(self):
extra_args = [["-debug=1"] for _ in range(self.num_nodes)]
- for i, import_node in enumerate(IMPORT_NODES, 1):
+ for i, import_node in enumerate(IMPORT_NODES, 2):
if import_node.prune:
extra_args[i] += ["-prune=1"]
@@ -123,9 +129,9 @@ class ImportRescanTest(BitcoinTestFramework):
# each possible type of wallet import RPC.
for i, variant in enumerate(IMPORT_VARIANTS):
variant.label = "label {} {}".format(i, variant)
- variant.address = self.nodes[0].validateaddress(self.nodes[0].getnewaddress(variant.label))
- variant.key = self.nodes[0].dumpprivkey(variant.address["address"])
- variant.initial_amount = 25 - (i + 1) / 4.0
+ variant.address = self.nodes[1].validateaddress(self.nodes[1].getnewaddress(variant.label))
+ variant.key = self.nodes[1].dumpprivkey(variant.address["address"])
+ variant.initial_amount = 10 - (i + 1) / 4.0
variant.initial_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.initial_amount)
# Generate a block containing the initial transactions, then another
@@ -142,7 +148,7 @@ class ImportRescanTest(BitcoinTestFramework):
for variant in IMPORT_VARIANTS:
variant.expect_disabled = variant.rescan == Rescan.yes and variant.prune and variant.call == Call.single
expect_rescan = variant.rescan == Rescan.yes and not variant.expect_disabled
- variant.node = self.nodes[1 + IMPORT_NODES.index(ImportNode(variant.prune, expect_rescan))]
+ variant.node = self.nodes[2 + IMPORT_NODES.index(ImportNode(variant.prune, expect_rescan))]
variant.do_import(timestamp)
if expect_rescan:
variant.expected_balance = variant.initial_amount
@@ -156,7 +162,7 @@ class ImportRescanTest(BitcoinTestFramework):
# Create new transactions sending to each address.
fee = self.nodes[0].getnetworkinfo()["relayfee"]
for i, variant in enumerate(IMPORT_VARIANTS):
- variant.sent_amount = 25 - (2 * i + 1) / 8.0
+ variant.sent_amount = 10 - (2 * i + 1) / 8.0
variant.sent_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.sent_amount)
# Generate a block containing the new transactions.
diff --git a/src/init.cpp b/src/init.cpp
index 7c108ac4a6..5820d8f57c 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -801,6 +801,19 @@ ServiceFlags nLocalServices = NODE_NETWORK;
}
+[[noreturn]] static void new_handler_terminate()
+{
+ // Rather than throwing std::bad-alloc if allocation fails, terminate
+ // immediately to (try to) avoid chain corruption.
+ // Since LogPrintf may itself allocate memory, set the handler directly
+ // to terminate first.
+ std::set_new_handler(std::terminate);
+ LogPrintf("Error: Out of memory. Terminating.\n");
+
+ // The log was successful, terminate now.
+ std::terminate();
+};
+
bool AppInitBasicSetup()
{
// ********************************************************* Step 1: setup
@@ -853,6 +866,9 @@ bool AppInitBasicSetup()
// Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
signal(SIGPIPE, SIG_IGN);
#endif
+
+ std::set_new_handler(new_handler_terminate);
+
return true;
}
diff --git a/src/prevector.h b/src/prevector.h
index 6b2f578f5c..cba2e30057 100644
--- a/src/prevector.h
+++ b/src/prevector.h
@@ -5,6 +5,7 @@
#ifndef _BITCOIN_PREVECTOR_H_
#define _BITCOIN_PREVECTOR_H_
+#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
@@ -170,10 +171,15 @@ private:
}
} else {
if (!is_direct()) {
+ /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert
+ success. These should instead use an allocator or new/delete so that handlers
+ are called as necessary, but performance would be slightly degraded by doing so. */
_union.indirect = static_cast<char*>(realloc(_union.indirect, ((size_t)sizeof(T)) * new_capacity));
+ assert(_union.indirect);
_union.capacity = new_capacity;
} else {
char* new_indirect = static_cast<char*>(malloc(((size_t)sizeof(T)) * new_capacity));
+ assert(new_indirect);
T* src = direct_ptr(0);
T* dst = reinterpret_cast<T*>(new_indirect);
memcpy(dst, src, size() * sizeof(T));
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index d32e8ba06a..43d7e3c617 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -397,6 +397,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
{
CWallet wallet;
+ CWallet *backup = ::pwalletMain;
::pwalletMain = &wallet;
UniValue key;
key.setObject();
@@ -412,6 +413,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain100Setup)
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.\"}}]", newTip->GetBlockTimeMax()));
+ ::pwalletMain = backup;
}
}