aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rwxr-xr-xcontrib/install_db4.sh2
-rw-r--r--doc/build-osx.md2
-rw-r--r--doc/build-unix.md2
-rw-r--r--doc/developer-notes.md2
-rw-r--r--src/Makefile.test.include1
-rw-r--r--src/core_io.h2
-rw-r--r--src/core_read.cpp34
-rw-r--r--src/policy/fees.cpp68
-rw-r--r--src/rpc/client.cpp2
-rw-r--r--src/rpc/rawtransaction.cpp16
-rw-r--r--src/test/miner_tests.cpp24
-rw-r--r--src/test/rpc_tests.cpp4
-rw-r--r--src/test/univalue_tests.cpp333
-rw-r--r--src/univalue/.travis.yml1
-rw-r--r--src/univalue/test/object.cpp3
-rw-r--r--src/wallet/rpcwallet.cpp16
-rw-r--r--src/wallet/walletdb.cpp4
-rwxr-xr-xtest/functional/conf_args.py49
-rwxr-xr-xtest/functional/node_network_limited.py88
-rwxr-xr-xtest/functional/rawtransactions.py11
-rw-r--r--test/functional/test_framework/messages.py3
-rwxr-xr-xtest/functional/test_runner.py1
23 files changed, 186 insertions, 485 deletions
diff --git a/configure.ac b/configure.ac
index a05896edea..f7de4c9f9a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -761,6 +761,9 @@ define(MINIMUM_REQUIRED_BOOST, 1.47.0)
dnl Check for boost libs
AX_BOOST_BASE([MINIMUM_REQUIRED_BOOST])
+if test x$want_boost = xno; then
+ AC_MSG_ERROR([[only libbitcoinconsensus can be built without boost]])
+fi
AX_BOOST_SYSTEM
AX_BOOST_FILESYSTEM
AX_BOOST_PROGRAM_OPTIONS
diff --git a/contrib/install_db4.sh b/contrib/install_db4.sh
index 1d33e8d3ba..319c74b43d 100755
--- a/contrib/install_db4.sh
+++ b/contrib/install_db4.sh
@@ -7,7 +7,7 @@ set -e
if [ -z "${1}" ]; then
echo "Usage: ./install_db4.sh <base-dir> [<extra-bdb-configure-flag> ...]"
echo
- echo "Must specify a single argument: the directory in which db5 will be built."
+ echo "Must specify a single argument: the directory in which db4 will be built."
echo "This is probably \`pwd\` if you're at the root of the bitcoin repository."
exit 1
fi
diff --git a/doc/build-osx.md b/doc/build-osx.md
index 6663016ed8..cbc5288c16 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -29,7 +29,7 @@ NOTE: Building with Qt4 is still supported, however, could result in a broken UI
Berkeley DB
-----------
It is recommended to use Berkeley DB 4.8. If you have to build it yourself,
-you can use [the installation script included in contrib/](contrib/install_db4.sh)
+you can use [the installation script included in contrib/](/contrib/install_db4.sh)
like so
```shell
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 5d3329e2cf..8716ba35d1 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -166,7 +166,7 @@ turned off by default. See the configure options for upnp behavior desired:
Berkeley DB
-----------
It is recommended to use Berkeley DB 4.8. If you have to build it yourself,
-you can use [the installation script included in contrib/](contrib/install_db4.sh)
+you can use [the installation script included in contrib/](/contrib/install_db4.sh)
like so
```shell
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 7f34b07d15..9dc63a1e4b 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -493,7 +493,7 @@ namespace {
- *Rationale*: Avoids confusion about the namespace context
- Prefer `#include <primitives/transaction.h>` bracket syntax instead of
- `#include "primitives/transactions.h"`` quote syntax when possible.
+ `#include "primitives/transactions.h"` quote syntax when possible.
- *Rationale*: Bracket syntax is less ambiguous because the preprocessor
searches a fixed list of include directories without taking location of the
diff --git a/src/Makefile.test.include b/src/Makefile.test.include
index 06175be3fc..49a814c3f6 100644
--- a/src/Makefile.test.include
+++ b/src/Makefile.test.include
@@ -84,7 +84,6 @@ BITCOIN_TESTS =\
test/txvalidationcache_tests.cpp \
test/versionbits_tests.cpp \
test/uint256_tests.cpp \
- test/univalue_tests.cpp \
test/util_tests.cpp
if ENABLE_WALLET
diff --git a/src/core_io.h b/src/core_io.h
index 7ed84d6665..3cdae06dfb 100644
--- a/src/core_io.h
+++ b/src/core_io.h
@@ -20,7 +20,7 @@ class UniValue;
// core_read.cpp
CScript ParseScript(const std::string& s);
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
-bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness = false);
+bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness = false, bool try_witness = true);
bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
uint256 ParseHashUV(const UniValue& v, const std::string& strName);
uint256 ParseHashStr(const std::string&, const std::string& strName);
diff --git a/src/core_read.cpp b/src/core_read.cpp
index 2f5b67b5c7..4f2dabe10f 100644
--- a/src/core_read.cpp
+++ b/src/core_read.cpp
@@ -108,39 +108,39 @@ bool CheckTxScriptsSanity(const CMutableTransaction& tx)
return true;
}
-bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx, bool fTryNoWitness)
+bool DecodeHexTx(CMutableTransaction& tx, const std::string& hex_tx, bool try_no_witness, bool try_witness)
{
- if (!IsHex(strHexTx)) {
+ if (!IsHex(hex_tx)) {
return false;
}
- std::vector<unsigned char> txData(ParseHex(strHexTx));
+ std::vector<unsigned char> txData(ParseHex(hex_tx));
- if (fTryNoWitness) {
+ if (try_no_witness) {
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
try {
ssData >> tx;
- if (ssData.eof() && CheckTxScriptsSanity(tx)) {
+ if (ssData.eof() && (!try_witness || CheckTxScriptsSanity(tx))) {
return true;
}
- }
- catch (const std::exception&) {
+ } catch (const std::exception&) {
// Fall through.
}
}
- CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
- try {
- ssData >> tx;
- if (!ssData.empty()) {
- return false;
+ if (try_witness) {
+ CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
+ try {
+ ssData >> tx;
+ if (ssData.empty()) {
+ return true;
+ }
+ } catch (const std::exception&) {
+ // Fall through.
}
}
- catch (const std::exception&) {
- return false;
- }
-
- return true;
+
+ return false;
}
bool DecodeHexBlk(CBlock& block, const std::string& strHexBlk)
diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index dc88c4f91a..490986fc11 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -411,15 +411,13 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets
size_t maxConfirms, maxPeriods;
// The current version will store the decay with each individual TxConfirmStats and also keep a scale factor
- if (nFileVersion >= 149900) {
- filein >> decay;
- if (decay <= 0 || decay >= 1) {
- throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
- }
- filein >> scale;
- if (scale == 0) {
- throw std::runtime_error("Corrupt estimates file. Scale must be non-zero");
- }
+ filein >> decay;
+ if (decay <= 0 || decay >= 1) {
+ throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
+ }
+ filein >> scale;
+ if (scale == 0) {
+ throw std::runtime_error("Corrupt estimates file. Scale must be non-zero");
}
filein >> avg;
@@ -443,20 +441,13 @@ void TxConfirmStats::Read(CAutoFile& filein, int nFileVersion, size_t numBuckets
}
}
- if (nFileVersion >= 149900) {
- filein >> failAvg;
- if (maxPeriods != failAvg.size()) {
- throw std::runtime_error("Corrupt estimates file. Mismatch in confirms tracked for failures");
- }
- for (unsigned int i = 0; i < maxPeriods; i++) {
- if (failAvg[i].size() != numBuckets) {
- throw std::runtime_error("Corrupt estimates file. Mismatch in one of failure average bucket counts");
- }
- }
- } else {
- failAvg.resize(confAvg.size());
- for (unsigned int i = 0; i < failAvg.size(); i++) {
- failAvg[i].resize(numBuckets);
+ filein >> failAvg;
+ if (maxPeriods != failAvg.size()) {
+ throw std::runtime_error("Corrupt estimates file. Mismatch in confirms tracked for failures");
+ }
+ for (unsigned int i = 0; i < maxPeriods; i++) {
+ if (failAvg[i].size() != numBuckets) {
+ throw std::runtime_error("Corrupt estimates file. Mismatch in one of failure average bucket counts");
}
}
@@ -563,7 +554,7 @@ void CBlockPolicyEstimator::processTransaction(const CTxMemPoolEntry& entry, boo
if (mapMemPoolTxs.count(hash)) {
LogPrint(BCLog::ESTIMATEFEE, "Blockpolicy error mempool tx %s already being tracked\n",
hash.ToString().c_str());
- return;
+ return;
}
if (txHeight != nBestSeenHeight) {
@@ -944,32 +935,9 @@ bool CBlockPolicyEstimator::Read(CAutoFile& filein)
unsigned int nFileBestSeenHeight;
filein >> nFileBestSeenHeight;
- if (nVersionThatWrote < 149900) {
- // Read the old fee estimates file for temporary use, but then discard. Will start collecting data from scratch.
- // decay is stored before buckets in old versions, so pre-read decay and pass into TxConfirmStats constructor
- double tempDecay;
- filein >> tempDecay;
- if (tempDecay <= 0 || tempDecay >= 1)
- throw std::runtime_error("Corrupt estimates file. Decay must be between 0 and 1 (non-inclusive)");
-
- std::vector<double> tempBuckets;
- filein >> tempBuckets;
- size_t tempNum = tempBuckets.size();
- if (tempNum <= 1 || tempNum > 1000)
- throw std::runtime_error("Corrupt estimates file. Must have between 2 and 1000 feerate buckets");
-
- std::map<double, unsigned int> tempMap;
-
- std::unique_ptr<TxConfirmStats> tempFeeStats(new TxConfirmStats(tempBuckets, tempMap, MED_BLOCK_PERIODS, tempDecay, 1));
- tempFeeStats->Read(filein, nVersionThatWrote, tempNum);
- // if nVersionThatWrote < 139900 then another TxConfirmStats (for priority) follows but can be ignored.
-
- tempMap.clear();
- for (unsigned int i = 0; i < tempBuckets.size(); i++) {
- tempMap[tempBuckets[i]] = i;
- }
- }
- else { // nVersionThatWrote >= 149900
+ if (nVersionRequired < 149900) {
+ LogPrintf("%s: incompatible old fee estimation data (non-fatal). Version: %d\n", __func__, nVersionRequired);
+ } else { // New format introduced in 149900
unsigned int nFileHistoricalFirst, nFileHistoricalBest;
filein >> nFileHistoricalFirst >> nFileHistoricalBest;
if (nFileHistoricalFirst > nFileHistoricalBest || nFileHistoricalBest > nFileBestSeenHeight) {
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index f2fa114313..e641493e1e 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -91,11 +91,13 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "createrawtransaction", 1, "outputs" },
{ "createrawtransaction", 2, "locktime" },
{ "createrawtransaction", 3, "replaceable" },
+ { "decoderawtransaction", 1, "iswitness" },
{ "signrawtransaction", 1, "prevtxs" },
{ "signrawtransaction", 2, "privkeys" },
{ "sendrawtransaction", 1, "allowhighfees" },
{ "combinerawtransaction", 0, "txs" },
{ "fundrawtransaction", 1, "options" },
+ { "fundrawtransaction", 2, "iswitness" },
{ "gettxout", 1, "n" },
{ "gettxout", 2, "include_mempool" },
{ "gettxoutproof", 0, "txids" },
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index fbebdf44d4..1049131d5e 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -441,13 +441,15 @@ UniValue createrawtransaction(const JSONRPCRequest& request)
UniValue decoderawtransaction(const JSONRPCRequest& request)
{
- if (request.fHelp || request.params.size() != 1)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
throw std::runtime_error(
- "decoderawtransaction \"hexstring\"\n"
+ "decoderawtransaction \"hexstring\" ( iswitness )\n"
"\nReturn a JSON object representing the serialized, hex-encoded transaction.\n"
"\nArguments:\n"
"1. \"hexstring\" (string, required) The transaction hex string\n"
+ "2. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction\n"
+ " If iswitness is not present, heuristic tests will be used in decoding\n"
"\nResult:\n"
"{\n"
@@ -495,12 +497,16 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
);
LOCK(cs_main);
- RPCTypeCheck(request.params, {UniValue::VSTR});
+ RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VBOOL});
CMutableTransaction mtx;
- if (!DecodeHexTx(mtx, request.params[0].get_str(), true))
+ bool try_witness = request.params[1].isNull() ? true : request.params[1].get_bool();
+ bool try_no_witness = request.params[1].isNull() ? true : !request.params[1].get_bool();
+
+ if (!DecodeHexTx(mtx, request.params[0].get_str(), try_no_witness, try_witness)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ }
UniValue result(UniValue::VOBJ);
TxToUniv(CTransaction(std::move(mtx)), uint256(), result, false);
@@ -1016,7 +1022,7 @@ static const CRPCCommand commands[] =
// --------------------- ------------------------ ----------------------- ----------
{ "rawtransactions", "getrawtransaction", &getrawtransaction, {"txid","verbose","blockhash"} },
{ "rawtransactions", "createrawtransaction", &createrawtransaction, {"inputs","outputs","locktime","replaceable"} },
- { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring"} },
+ { "rawtransactions", "decoderawtransaction", &decoderawtransaction, {"hexstring","iswitness"} },
{ "rawtransactions", "decodescript", &decodescript, {"hexstring"} },
{ "rawtransactions", "sendrawtransaction", &sendrawtransaction, {"hexstring","allowhighfees"} },
{ "rawtransactions", "combinerawtransaction", &combinerawtransaction, {"txs"} },
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index b1a2032ea8..97c548dbb0 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -26,6 +26,17 @@
BOOST_FIXTURE_TEST_SUITE(miner_tests, TestingSetup)
+// BOOST_CHECK_EXCEPTION predicates to check the specific validation error
+class HasReason {
+public:
+ HasReason(const std::string& reason) : m_reason(reason) {}
+ bool operator() (const std::runtime_error& e) const {
+ return std::string(e.what()).find(m_reason) != std::string::npos;
+ };
+private:
+ const std::string m_reason;
+};
+
static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);
static BlockAssembler AssemblerForTest(const CChainParams& params) {
@@ -264,7 +275,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx));
tx.vin[0].prevout.hash = hash;
}
- BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
+
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-blk-sigops"));
mempool.clear();
tx.vin[0].prevout.hash = txFirst[0]->GetHash();
@@ -304,7 +316,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
// orphan in mempool, template creation fails
hash = tx.GetHash();
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).FromTx(tx));
- BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
mempool.clear();
// child with higher feerate than parent
@@ -332,7 +344,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
hash = tx.GetHash();
// give it a fee so it'll get mined
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
- BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
+ // Should throw bad-cb-multiple
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple"));
mempool.clear();
// double spend txn pair in mempool, template creation fails
@@ -345,7 +358,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].scriptPubKey = CScript() << OP_2;
hash = tx.GetHash();
mempool.addUnchecked(hash, entry.Fee(HIGHFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx));
- BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));
mempool.clear();
// subsidy changing
@@ -389,7 +402,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue -= LOWFEE;
hash = tx.GetHash();
mempool.addUnchecked(hash, entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx));
- BOOST_CHECK_THROW(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error);
+ // Should throw block-validation-failed
+ BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed"));
mempool.clear();
// Delete the dummy blocks again.
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 710d09ead6..c69b5f1ca3 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -65,7 +65,9 @@ BOOST_AUTO_TEST_CASE(rpc_rawparams)
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "size").get_int(), 193);
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "version").get_int(), 1);
BOOST_CHECK_EQUAL(find_value(r.get_obj(), "locktime").get_int(), 0);
- BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error);
+ BOOST_CHECK_THROW(CallRPC(std::string("decoderawtransaction ")+rawtx+" extra"), std::runtime_error);
+ BOOST_CHECK_NO_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false"));
+ BOOST_CHECK_THROW(r = CallRPC(std::string("decoderawtransaction ")+rawtx+" false extra"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("signrawtransaction"), std::runtime_error);
BOOST_CHECK_THROW(CallRPC("signrawtransaction null"), std::runtime_error);
diff --git a/src/test/univalue_tests.cpp b/src/test/univalue_tests.cpp
deleted file mode 100644
index 7386204437..0000000000
--- a/src/test/univalue_tests.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright (c) 2014 BitPay Inc.
-// 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.
-
-#include <stdint.h>
-#include <vector>
-#include <string>
-#include <map>
-#include <univalue.h>
-#include <test/test_bitcoin.h>
-
-#include <boost/test/unit_test.hpp>
-
-BOOST_FIXTURE_TEST_SUITE(univalue_tests, BasicTestingSetup)
-
-BOOST_AUTO_TEST_CASE(univalue_constructor)
-{
- UniValue v1;
- BOOST_CHECK(v1.isNull());
-
- UniValue v2(UniValue::VSTR);
- BOOST_CHECK(v2.isStr());
-
- UniValue v3(UniValue::VSTR, "foo");
- BOOST_CHECK(v3.isStr());
- BOOST_CHECK_EQUAL(v3.getValStr(), "foo");
-
- UniValue numTest;
- BOOST_CHECK(numTest.setNumStr("82"));
- BOOST_CHECK(numTest.isNum());
- BOOST_CHECK_EQUAL(numTest.getValStr(), "82");
-
- uint64_t vu64 = 82;
- UniValue v4(vu64);
- BOOST_CHECK(v4.isNum());
- BOOST_CHECK_EQUAL(v4.getValStr(), "82");
-
- int64_t vi64 = -82;
- UniValue v5(vi64);
- BOOST_CHECK(v5.isNum());
- BOOST_CHECK_EQUAL(v5.getValStr(), "-82");
-
- int vi = -688;
- UniValue v6(vi);
- BOOST_CHECK(v6.isNum());
- BOOST_CHECK_EQUAL(v6.getValStr(), "-688");
-
- double vd = -7.21;
- UniValue v7(vd);
- BOOST_CHECK(v7.isNum());
- BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21");
-
- std::string vs("yawn");
- UniValue v8(vs);
- BOOST_CHECK(v8.isStr());
- BOOST_CHECK_EQUAL(v8.getValStr(), "yawn");
-
- const char *vcs = "zappa";
- UniValue v9(vcs);
- BOOST_CHECK(v9.isStr());
- BOOST_CHECK_EQUAL(v9.getValStr(), "zappa");
-}
-
-BOOST_AUTO_TEST_CASE(univalue_typecheck)
-{
- UniValue v1;
- BOOST_CHECK(v1.setNumStr("1"));
- BOOST_CHECK(v1.isNum());
- BOOST_CHECK_THROW(v1.get_bool(), std::runtime_error);
-
- UniValue v2;
- BOOST_CHECK(v2.setBool(true));
- BOOST_CHECK_EQUAL(v2.get_bool(), true);
- BOOST_CHECK_THROW(v2.get_int(), std::runtime_error);
-
- UniValue v3;
- BOOST_CHECK(v3.setNumStr("32482348723847471234"));
- BOOST_CHECK_THROW(v3.get_int64(), std::runtime_error);
- BOOST_CHECK(v3.setNumStr("1000"));
- BOOST_CHECK_EQUAL(v3.get_int64(), 1000);
-
- UniValue v4;
- BOOST_CHECK(v4.setNumStr("2147483648"));
- BOOST_CHECK_EQUAL(v4.get_int64(), 2147483648);
- BOOST_CHECK_THROW(v4.get_int(), std::runtime_error);
- BOOST_CHECK(v4.setNumStr("1000"));
- BOOST_CHECK_EQUAL(v4.get_int(), 1000);
- BOOST_CHECK_THROW(v4.get_str(), std::runtime_error);
- BOOST_CHECK_EQUAL(v4.get_real(), 1000);
- BOOST_CHECK_THROW(v4.get_array(), std::runtime_error);
- BOOST_CHECK_THROW(v4.getKeys(), std::runtime_error);
- BOOST_CHECK_THROW(v4.getValues(), std::runtime_error);
- BOOST_CHECK_THROW(v4.get_obj(), std::runtime_error);
-
- UniValue v5;
- BOOST_CHECK(v5.read("[true, 10]"));
- BOOST_CHECK_NO_THROW(v5.get_array());
- std::vector<UniValue> vals = v5.getValues();
- BOOST_CHECK_THROW(vals[0].get_int(), std::runtime_error);
- BOOST_CHECK_EQUAL(vals[0].get_bool(), true);
-
- BOOST_CHECK_EQUAL(vals[1].get_int(), 10);
- BOOST_CHECK_THROW(vals[1].get_bool(), std::runtime_error);
-}
-
-BOOST_AUTO_TEST_CASE(univalue_set)
-{
- UniValue v(UniValue::VSTR, "foo");
- v.clear();
- BOOST_CHECK(v.isNull());
- BOOST_CHECK_EQUAL(v.getValStr(), "");
-
- BOOST_CHECK(v.setObject());
- BOOST_CHECK(v.isObject());
- BOOST_CHECK_EQUAL(v.size(), 0);
- BOOST_CHECK_EQUAL(v.getType(), UniValue::VOBJ);
- BOOST_CHECK(v.empty());
-
- BOOST_CHECK(v.setArray());
- BOOST_CHECK(v.isArray());
- BOOST_CHECK_EQUAL(v.size(), 0);
-
- BOOST_CHECK(v.setStr("zum"));
- BOOST_CHECK(v.isStr());
- BOOST_CHECK_EQUAL(v.getValStr(), "zum");
-
- BOOST_CHECK(v.setFloat(-1.01));
- BOOST_CHECK(v.isNum());
- BOOST_CHECK_EQUAL(v.getValStr(), "-1.01");
-
- BOOST_CHECK(v.setInt((int)1023));
- BOOST_CHECK(v.isNum());
- BOOST_CHECK_EQUAL(v.getValStr(), "1023");
-
- BOOST_CHECK(v.setInt((int64_t)-1023LL));
- BOOST_CHECK(v.isNum());
- BOOST_CHECK_EQUAL(v.getValStr(), "-1023");
-
- BOOST_CHECK(v.setInt((uint64_t)1023ULL));
- BOOST_CHECK(v.isNum());
- BOOST_CHECK_EQUAL(v.getValStr(), "1023");
-
- BOOST_CHECK(v.setNumStr("-688"));
- BOOST_CHECK(v.isNum());
- BOOST_CHECK_EQUAL(v.getValStr(), "-688");
-
- BOOST_CHECK(v.setBool(false));
- BOOST_CHECK_EQUAL(v.isBool(), true);
- BOOST_CHECK_EQUAL(v.isTrue(), false);
- BOOST_CHECK_EQUAL(v.isFalse(), true);
- BOOST_CHECK_EQUAL(v.getBool(), false);
-
- BOOST_CHECK(v.setBool(true));
- BOOST_CHECK_EQUAL(v.isBool(), true);
- BOOST_CHECK_EQUAL(v.isTrue(), true);
- BOOST_CHECK_EQUAL(v.isFalse(), false);
- BOOST_CHECK_EQUAL(v.getBool(), true);
-
- BOOST_CHECK(!v.setNumStr("zombocom"));
-
- BOOST_CHECK(v.setNull());
- BOOST_CHECK(v.isNull());
-}
-
-BOOST_AUTO_TEST_CASE(univalue_array)
-{
- UniValue arr(UniValue::VARR);
-
- UniValue v((int64_t)1023LL);
- BOOST_CHECK(arr.push_back(v));
-
- std::string vStr("zippy");
- BOOST_CHECK(arr.push_back(vStr));
-
- const char *s = "pippy";
- BOOST_CHECK(arr.push_back(s));
-
- std::vector<UniValue> vec;
- v.setStr("boing");
- vec.push_back(v);
-
- v.setStr("going");
- vec.push_back(v);
-
- BOOST_CHECK(arr.push_backV(vec));
-
- BOOST_CHECK_EQUAL(arr.empty(), false);
- BOOST_CHECK_EQUAL(arr.size(), 5);
-
- BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023");
- BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy");
- BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy");
- BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing");
- BOOST_CHECK_EQUAL(arr[4].getValStr(), "going");
-
- BOOST_CHECK_EQUAL(arr[999].getValStr(), "");
-
- arr.clear();
- BOOST_CHECK(arr.empty());
- BOOST_CHECK_EQUAL(arr.size(), 0);
-}
-
-BOOST_AUTO_TEST_CASE(univalue_object)
-{
- UniValue obj(UniValue::VOBJ);
- std::string strKey, strVal;
- UniValue v;
-
- strKey = "age";
- v.setInt(100);
- BOOST_CHECK(obj.pushKV(strKey, v));
-
- strKey = "first";
- strVal = "John";
- BOOST_CHECK(obj.pushKV(strKey, strVal));
-
- strKey = "last";
- const char *cVal = "Smith";
- BOOST_CHECK(obj.pushKV(strKey, cVal));
-
- strKey = "distance";
- BOOST_CHECK(obj.pushKV(strKey, (int64_t) 25));
-
- strKey = "time";
- BOOST_CHECK(obj.pushKV(strKey, (uint64_t) 3600));
-
- strKey = "calories";
- BOOST_CHECK(obj.pushKV(strKey, (int) 12));
-
- strKey = "temperature";
- BOOST_CHECK(obj.pushKV(strKey, (double) 90.012));
-
- UniValue obj2(UniValue::VOBJ);
- BOOST_CHECK(obj2.pushKV("cat1", 9000));
- BOOST_CHECK(obj2.pushKV("cat2", 12345));
-
- BOOST_CHECK(obj.pushKVs(obj2));
-
- BOOST_CHECK_EQUAL(obj.empty(), false);
- BOOST_CHECK_EQUAL(obj.size(), 9);
-
- BOOST_CHECK_EQUAL(obj["age"].getValStr(), "100");
- BOOST_CHECK_EQUAL(obj["first"].getValStr(), "John");
- BOOST_CHECK_EQUAL(obj["last"].getValStr(), "Smith");
- BOOST_CHECK_EQUAL(obj["distance"].getValStr(), "25");
- BOOST_CHECK_EQUAL(obj["time"].getValStr(), "3600");
- BOOST_CHECK_EQUAL(obj["calories"].getValStr(), "12");
- BOOST_CHECK_EQUAL(obj["temperature"].getValStr(), "90.012");
- BOOST_CHECK_EQUAL(obj["cat1"].getValStr(), "9000");
- BOOST_CHECK_EQUAL(obj["cat2"].getValStr(), "12345");
-
- BOOST_CHECK_EQUAL(obj["nyuknyuknyuk"].getValStr(), "");
-
- BOOST_CHECK(obj.exists("age"));
- BOOST_CHECK(obj.exists("first"));
- BOOST_CHECK(obj.exists("last"));
- BOOST_CHECK(obj.exists("distance"));
- BOOST_CHECK(obj.exists("time"));
- BOOST_CHECK(obj.exists("calories"));
- BOOST_CHECK(obj.exists("temperature"));
- BOOST_CHECK(obj.exists("cat1"));
- BOOST_CHECK(obj.exists("cat2"));
-
- BOOST_CHECK(!obj.exists("nyuknyuknyuk"));
-
- std::map<std::string, UniValue::VType> objTypes;
- objTypes["age"] = UniValue::VNUM;
- objTypes["first"] = UniValue::VSTR;
- objTypes["last"] = UniValue::VSTR;
- objTypes["distance"] = UniValue::VNUM;
- objTypes["time"] = UniValue::VNUM;
- objTypes["calories"] = UniValue::VNUM;
- objTypes["temperature"] = UniValue::VNUM;
- objTypes["cat1"] = UniValue::VNUM;
- objTypes["cat2"] = UniValue::VNUM;
- BOOST_CHECK(obj.checkObject(objTypes));
-
- objTypes["cat2"] = UniValue::VSTR;
- BOOST_CHECK(!obj.checkObject(objTypes));
-
- obj.clear();
- BOOST_CHECK(obj.empty());
- BOOST_CHECK_EQUAL(obj.size(), 0);
-}
-
-static const char *json1 =
-"[1.10000000,{\"key1\":\"str\\u0000\",\"key2\":800,\"key3\":{\"name\":\"martian http://test.com\"}}]";
-
-BOOST_AUTO_TEST_CASE(univalue_readwrite)
-{
- UniValue v;
- BOOST_CHECK(v.read(json1));
-
- std::string strJson1(json1);
- BOOST_CHECK(v.read(strJson1));
-
- BOOST_CHECK(v.isArray());
- BOOST_CHECK_EQUAL(v.size(), 2);
-
- BOOST_CHECK_EQUAL(v[0].getValStr(), "1.10000000");
-
- UniValue obj = v[1];
- BOOST_CHECK(obj.isObject());
- BOOST_CHECK_EQUAL(obj.size(), 3);
-
- BOOST_CHECK(obj["key1"].isStr());
- std::string correctValue("str");
- correctValue.push_back('\0');
- BOOST_CHECK_EQUAL(obj["key1"].getValStr(), correctValue);
- BOOST_CHECK(obj["key2"].isNum());
- BOOST_CHECK_EQUAL(obj["key2"].getValStr(), "800");
- BOOST_CHECK(obj["key3"].isObject());
-
- BOOST_CHECK_EQUAL(strJson1, v.write());
-
- /* Check for (correctly reporting) a parsing error if the initial
- JSON construct is followed by more stuff. Note that whitespace
- is, of course, exempt. */
-
- BOOST_CHECK(v.read(" {}\n "));
- BOOST_CHECK(v.isObject());
- BOOST_CHECK(v.read(" []\n "));
- BOOST_CHECK(v.isArray());
-
- BOOST_CHECK(!v.read("@{}"));
- BOOST_CHECK(!v.read("{} garbage"));
- BOOST_CHECK(!v.read("[]{}"));
- BOOST_CHECK(!v.read("{}[]"));
- BOOST_CHECK(!v.read("{} 42"));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/univalue/.travis.yml b/src/univalue/.travis.yml
index 132743d349..43a1ed362e 100644
--- a/src/univalue/.travis.yml
+++ b/src/univalue/.travis.yml
@@ -25,7 +25,6 @@ addons:
- pkg-config
before_script:
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew uninstall libtool; brew install libtool; fi
- if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi
- test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh
diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp
index 02446292a1..679cc9f143 100644
--- a/src/univalue/test/object.cpp
+++ b/src/univalue/test/object.cpp
@@ -19,9 +19,10 @@
#define BOOST_CHECK_THROW(stmt, excMatch) { \
try { \
(stmt); \
+ assert(0 && "No exception caught"); \
} catch (excMatch & e) { \
} catch (...) { \
- assert(0); \
+ assert(0 && "Wrong exception caught"); \
} \
}
#define BOOST_CHECK_NO_THROW(stmt) { \
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 4da56fbe8a..f839a18612 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -2982,9 +2982,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
return NullUniValue;
}
- if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
+ if (request.fHelp || request.params.size() < 1 || request.params.size() > 3)
throw std::runtime_error(
- "fundrawtransaction \"hexstring\" ( options )\n"
+ "fundrawtransaction \"hexstring\" ( options iswitness )\n"
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
"This will not modify existing inputs, and will add at most one change output to the outputs.\n"
"No existing outputs will be modified unless \"subtractFeeFromOutputs\" is specified.\n"
@@ -3019,6 +3019,9 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
" \"CONSERVATIVE\"\n"
" }\n"
" for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
+ "3. iswitness (boolean, optional) Whether the transaction hex is a serialized witness transaction \n"
+ " If iswitness is not present, heuristic tests will be used in decoding\n"
+
"\nResult:\n"
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
@@ -3055,7 +3058,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
coinControl.fAllowWatchOnly = request.params[1].get_bool();
}
else {
- RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ});
+ RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VOBJ, UniValue::VBOOL});
UniValue options = request.params[1];
@@ -3124,8 +3127,11 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
// parse hex string from parameter
CMutableTransaction tx;
- if (!DecodeHexTx(tx, request.params[0].get_str(), true))
+ bool try_witness = request.params[2].isNull() ? true : request.params[2].get_bool();
+ bool try_no_witness = request.params[2].isNull() ? true : !request.params[2].get_bool();
+ if (!DecodeHexTx(tx, request.params[0].get_str(), try_no_witness, try_witness)) {
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
+ }
if (tx.vout.size() == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
@@ -3443,7 +3449,7 @@ extern UniValue rescanblockchain(const JSONRPCRequest& request);
static const CRPCCommand commands[] =
{ // category name actor (function) argNames
// --------------------- ------------------------ ----------------------- ----------
- { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options"} },
+ { "rawtransactions", "fundrawtransaction", &fundrawtransaction, {"hexstring","options","iswitness"} },
{ "hidden", "resendwallettransactions", &resendwallettransactions, {} },
{ "wallet", "abandontransaction", &abandontransaction, {"txid"} },
{ "wallet", "abortrescan", &abortrescan, {} },
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index efc50f72eb..0b0d84708d 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -626,7 +626,6 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx)
{
- bool fNoncriticalErrors = false;
DBErrors result = DB_LOAD_OK;
try {
@@ -681,9 +680,6 @@ DBErrors CWalletDB::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWal
result = DB_CORRUPT;
}
- if (fNoncriticalErrors && result == DB_LOAD_OK)
- result = DB_NONCRITICAL_ERROR;
-
return result;
}
diff --git a/test/functional/conf_args.py b/test/functional/conf_args.py
new file mode 100755
index 0000000000..61abba8082
--- /dev/null
+++ b/test/functional/conf_args.py
@@ -0,0 +1,49 @@
+#!/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 various command line arguments and configuration file parameters."""
+
+import os
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import get_datadir_path
+
+class ConfArgsTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ def run_test(self):
+ self.stop_node(0)
+ # Remove the -datadir argument so it doesn't override the config file
+ self.nodes[0].args = [arg for arg in self.nodes[0].args if not arg.startswith("-datadir")]
+
+ default_data_dir = get_datadir_path(self.options.tmpdir, 0)
+ new_data_dir = os.path.join(default_data_dir, 'newdatadir')
+ new_data_dir_2 = os.path.join(default_data_dir, 'newdatadir2')
+
+ # Check that using -datadir argument on non-existent directory fails
+ self.nodes[0].datadir = new_data_dir
+ self.assert_start_raises_init_error(0, ['-datadir='+new_data_dir], 'Error: Specified data directory "' + new_data_dir + '" does not exist.')
+
+ # Check that using non-existent datadir in conf file fails
+ conf_file = os.path.join(default_data_dir, "bitcoin.conf")
+ with open(conf_file, 'a', encoding='utf8') as f:
+ f.write("datadir=" + new_data_dir + "\n")
+ self.assert_start_raises_init_error(0, ['-conf='+conf_file], 'Error reading configuration file: specified data directory "' + new_data_dir + '" does not exist.')
+
+ # Create the directory and ensure the config file now works
+ os.mkdir(new_data_dir)
+ self.start_node(0, ['-conf='+conf_file, '-wallet=w1'])
+ self.stop_node(0)
+ assert os.path.isfile(os.path.join(new_data_dir, 'regtest', 'wallets', 'w1'))
+
+ # Ensure command line argument overrides datadir in conf
+ os.mkdir(new_data_dir_2)
+ self.nodes[0].datadir = new_data_dir_2
+ self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2'])
+ assert os.path.isfile(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2'))
+
+if __name__ == '__main__':
+ ConfArgsTest().main()
diff --git a/test/functional/node_network_limited.py b/test/functional/node_network_limited.py
index 6d1bf7ced2..70415e0168 100755
--- a/test/functional/node_network_limited.py
+++ b/test/functional/node_network_limited.py
@@ -2,15 +2,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.
+"""Tests NODE_NETWORK_LIMITED.
+
+Tests that a node configured with -prune=550 signals NODE_NETWORK_LIMITED correctly
+and that it responds to getdata requests for blocks correctly:
+ - send a block within 288 + 2 of the tip
+ - disconnect peers who request blocks older than that."""
+from test_framework.messages import CInv, msg_getdata
+from test_framework.mininode import NODE_BLOOM, NODE_NETWORK_LIMITED, NODE_WITNESS, NetworkThread, P2PInterface
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
-from test_framework.mininode import *
+from test_framework.util import assert_equal
-class BaseNode(P2PInterface):
- nServices = 0
- firstAddrnServices = 0
- def on_version(self, message):
- self.nServices = message.nServices
+class P2PIgnoreInv(P2PInterface):
+ def on_inv(self, message):
+ # The node will send us invs for other blocks. Ignore them.
+ pass
+
+ def send_getdata_for_block(self, blockhash):
+ getdata_request = msg_getdata()
+ getdata_request.inv.append(CInv(2, int(blockhash, 16)))
+ self.send_message(getdata_request)
class NodeNetworkLimitedTest(BitcoinTestFramework):
def set_test_params(self):
@@ -18,64 +29,29 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
self.num_nodes = 1
self.extra_args = [['-prune=550']]
- def getSignaledServiceFlags(self):
- node = self.nodes[0].add_p2p_connection(BaseNode())
+ def run_test(self):
+ node = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
NetworkThread().start()
node.wait_for_verack()
- services = node.nServices
- self.nodes[0].disconnect_p2ps()
- node.wait_for_disconnect()
- return services
- def tryGetBlockViaGetData(self, blockhash, must_disconnect):
- node = self.nodes[0].add_p2p_connection(BaseNode())
- NetworkThread().start()
- node.wait_for_verack()
- node.send_message(msg_verack())
- getdata_request = msg_getdata()
- getdata_request.inv.append(CInv(2, int(blockhash, 16)))
- node.send_message(getdata_request)
+ expected_services = NODE_BLOOM | NODE_WITNESS | NODE_NETWORK_LIMITED
- if (must_disconnect):
- #ensure we get disconnected
- node.wait_for_disconnect(5)
- else:
- # check if the peer sends us the requested block
- node.wait_for_block(int(blockhash, 16), 3)
- self.nodes[0].disconnect_p2ps()
- node.wait_for_disconnect()
+ self.log.info("Check that node has signalled expected services.")
+ assert_equal(node.nServices, expected_services)
- def run_test(self):
- #NODE_BLOOM & NODE_WITNESS & NODE_NETWORK_LIMITED must now be signaled
- assert_equal(self.getSignaledServiceFlags(), 1036) #1036 == 0x40C == 0100 0000 1100
-# | ||
-# | |^--- NODE_BLOOM
-# | ^---- NODE_WITNESS
-# ^-- NODE_NETWORK_LIMITED
+ self.log.info("Check that the localservices is as expected.")
+ assert_equal(int(self.nodes[0].getnetworkinfo()['localservices'], 16), expected_services)
- #now mine some blocks over the NODE_NETWORK_LIMITED + 2(racy buffer ext.) target
- firstblock = self.nodes[0].generate(1)[0]
+ self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
blocks = self.nodes[0].generate(292)
- blockWithinLimitedRange = blocks[-1]
-
- #make sure we can max retrive block at tip-288
- #requesting block at height 2 (tip-289) must fail (ignored)
- self.tryGetBlockViaGetData(firstblock, True) #first block must lead to disconnect
- self.tryGetBlockViaGetData(blocks[1], False) #last block in valid range
- self.tryGetBlockViaGetData(blocks[0], True) #first block outside of the 288+2 limit
-
- #NODE_NETWORK_LIMITED must still be signaled after restart
- self.restart_node(0)
- assert_equal(self.getSignaledServiceFlags(), 1036)
-
- #test the RPC service flags
- assert_equal(self.nodes[0].getnetworkinfo()['localservices'], "000000000000040c")
- # getdata a block above the NODE_NETWORK_LIMITED threshold must be possible
- self.tryGetBlockViaGetData(blockWithinLimitedRange, False)
+ self.log.info("Make sure we can max retrive block at tip-288.")
+ node.send_getdata_for_block(blocks[1]) # last block in valid range
+ node.wait_for_block(int(blocks[1], 16), timeout=3)
- # getdata a block below the NODE_NETWORK_LIMITED threshold must be ignored
- self.tryGetBlockViaGetData(firstblock, True)
+ self.log.info("Requesting block at height 2 (tip-289) must fail (ignored).")
+ node.send_getdata_for_block(blocks[0]) # first block outside of the 288+2 limit
+ node.wait_for_disconnect(5)
if __name__ == '__main__':
NodeNetworkLimitedTest().main()
diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py
index 20da577af1..aa519eb8e8 100755
--- a/test/functional/rawtransactions.py
+++ b/test/functional/rawtransactions.py
@@ -253,6 +253,17 @@ class RawTransactionsTest(BitcoinTestFramework):
self.sync_all()
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
+ # decoderawtransaction tests
+ # witness transaction
+ encrawtx = "010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000000000000"
+ decrawtx = self.nodes[0].decoderawtransaction(encrawtx, True) # decode as witness transaction
+ assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))
+ assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # force decode as non-witness transaction
+ # non-witness transaction
+ encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000"
+ decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction
+ assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))
+
# getrawtransaction tests
# 1. valid parameters - only supply txid
txHash = rawTx["hash"]
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index 2ab1bdac0f..d8032e4430 100644
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -38,10 +38,11 @@ COIN = 100000000 # 1 btc in satoshis
NODE_NETWORK = (1 << 0)
# NODE_GETUTXO = (1 << 1)
-# NODE_BLOOM = (1 << 2)
+NODE_BLOOM = (1 << 2)
NODE_WITNESS = (1 << 3)
NODE_UNSUPPORTED_SERVICE_BIT_5 = (1 << 5)
NODE_UNSUPPORTED_SERVICE_BIT_7 = (1 << 7)
+NODE_NETWORK_LIMITED = (1 << 10)
# Serialization/deserialization tools
def sha256(s):
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 58faec521d..bfd1192d3a 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -129,6 +129,7 @@ BASE_SCRIPTS= [
'p2p-acceptblock.py',
'feature_logging.py',
'node_network_limited.py',
+ 'conf_args.py',
]
EXTENDED_SCRIPTS = [