aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--contrib/debian/control2
-rw-r--r--contrib/gitian-descriptors/gitian-linux.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-osx.yml2
-rw-r--r--contrib/gitian-descriptors/gitian-win.yml2
-rw-r--r--doc/gitian-building.md6
-rw-r--r--doc/release-notes.md11
-rwxr-xr-xqa/rpc-tests/blockchain.py2
-rwxr-xr-xqa/rpc-tests/listtransactions.py109
-rw-r--r--share/setup.nsi.in2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/init.cpp3
-rw-r--r--src/main.cpp12
-rw-r--r--src/main.h3
-rw-r--r--src/policy/policy.cpp37
-rw-r--r--src/policy/rbf.cpp46
-rw-r--r--src/policy/rbf.h20
-rw-r--r--src/qt/rpcconsole.cpp4
-rw-r--r--src/script/standard.cpp21
-rw-r--r--src/script/standard.h1
-rw-r--r--src/test/script_P2SH_tests.cpp9
-rw-r--r--src/test/transaction_tests.cpp8
-rw-r--r--src/wallet/db.cpp2
-rw-r--r--src/wallet/rpcwallet.cpp22
24 files changed, 248 insertions, 82 deletions
diff --git a/README.md b/README.md
index 5bf56947d8..77d30db695 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@ Bitcoin Core integration/staging tree
[![Build Status](https://travis-ci.org/bitcoin/bitcoin.svg?branch=master)](https://travis-ci.org/bitcoin/bitcoin)
-https://www.bitcoin.org
+https://bitcoincore.org
What is Bitcoin?
----------------
diff --git a/contrib/debian/control b/contrib/debian/control
index 490b2571c3..fce6bc0118 100644
--- a/contrib/debian/control
+++ b/contrib/debian/control
@@ -23,7 +23,7 @@ Build-Depends: debhelper,
libprotobuf-dev, protobuf-compiler,
python
Standards-Version: 3.9.2
-Homepage: https://www.bitcoin.org/
+Homepage: https://bitcoincore.org/
Vcs-Git: git://github.com/bitcoin/bitcoin.git
Vcs-Browser: https://github.com/bitcoin/bitcoin
diff --git a/contrib/gitian-descriptors/gitian-linux.yml b/contrib/gitian-descriptors/gitian-linux.yml
index 80571fb05b..d13ae8b10c 100644
--- a/contrib/gitian-descriptors/gitian-linux.yml
+++ b/contrib/gitian-descriptors/gitian-linux.yml
@@ -15,6 +15,8 @@ packages:
- "faketime"
- "bsdmainutils"
- "binutils-gold"
+- "ca-certificates"
+- "python"
reference_datetime: "2016-01-01 00:00:00"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
diff --git a/contrib/gitian-descriptors/gitian-osx.yml b/contrib/gitian-descriptors/gitian-osx.yml
index 8064804b90..81888dea0f 100644
--- a/contrib/gitian-descriptors/gitian-osx.yml
+++ b/contrib/gitian-descriptors/gitian-osx.yml
@@ -18,6 +18,8 @@ packages:
- "libcap-dev"
- "libz-dev"
- "libbz2-dev"
+- "ca-certificates"
+- "python"
reference_datetime: "2016-01-01 00:00:00"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
diff --git a/contrib/gitian-descriptors/gitian-win.yml b/contrib/gitian-descriptors/gitian-win.yml
index 1475cd7eb2..66077e0d5b 100644
--- a/contrib/gitian-descriptors/gitian-win.yml
+++ b/contrib/gitian-descriptors/gitian-win.yml
@@ -18,6 +18,8 @@ packages:
- "g++-mingw-w64"
- "nsis"
- "zip"
+- "ca-certificates"
+- "python"
reference_datetime: "2016-01-01 00:00:00"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
diff --git a/doc/gitian-building.md b/doc/gitian-building.md
index 019e851696..e3fb944388 100644
--- a/doc/gitian-building.md
+++ b/doc/gitian-building.md
@@ -259,15 +259,15 @@ adduser debian sudo
Then set up LXC and the rest with the following, which is a complex jumble of settings and workarounds:
```bash
-# the version of lxc-start in Debian 7.4 needs to run as root, so make sure
+# the version of lxc-start in Debian needs to run as root, so make sure
# that the build script can execute it without providing a password
echo "%sudo ALL=NOPASSWD: /usr/bin/lxc-start" > /etc/sudoers.d/gitian-lxc
-# add cgroup for LXC
-echo "cgroup /sys/fs/cgroup cgroup defaults 0 0" >> /etc/fstab
# make /etc/rc.local script that sets up bridge between guest and host
echo '#!/bin/sh -e' > /etc/rc.local
echo 'brctl addbr br0' >> /etc/rc.local
echo 'ifconfig br0 10.0.3.2/24 up' >> /etc/rc.local
+echo 'iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE' >> /etc/rc.local
+echo 'echo 1 > /proc/sys/net/ipv4/ip_forward' >> /etc/rc.local
echo 'exit 0' >> /etc/rc.local
# make sure that USE_LXC is always set when logging in as debian,
# and configure LXC IP addresses
diff --git a/doc/release-notes.md b/doc/release-notes.md
index b8cb33405f..0b8339aae7 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -263,6 +263,17 @@ sanity check. Since 0.12, these are no longer stored. When loading a
0.12 wallet into an older version, it will automatically rescan to avoid
failed checks.
+Wallet: Pruning
+---------------
+
+With 0.12 it is possible to use wallet functionality in pruned mode.
+However, rescans as well as the RPCs `importwallet`, `importaddress`,
+`importprivkey` are disabled.
+
+To enable block pruning set `prune=<N>` on the command line or in
+`bitcoin.conf`, where `N` is the number of MiB to allot for
+raw block & undo data.
+
`NODE_BLOOM` service bit
------------------------
diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py
index daf6fb57a1..b0fc7b0172 100755
--- a/qa/rpc-tests/blockchain.py
+++ b/qa/rpc-tests/blockchain.py
@@ -80,7 +80,7 @@ class BlockchainTest(BitcoinTestFramework):
assert isinstance(header['mediantime'], int)
assert isinstance(header['nonce'], int)
assert isinstance(header['version'], int)
- assert isinstance(header['difficulty'], decimal.Decimal)
+ assert isinstance(header['difficulty'], Decimal)
if __name__ == '__main__':
BlockchainTest().main()
diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py
index 8a1e3dc4bc..f86f18de98 100755
--- a/qa/rpc-tests/listtransactions.py
+++ b/qa/rpc-tests/listtransactions.py
@@ -7,7 +7,15 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
+from test_framework.mininode import CTransaction
+import cStringIO
+import binascii
+def txFromHex(hexstring):
+ tx = CTransaction()
+ f = cStringIO.StringIO(binascii.unhexlify(hexstring))
+ tx.deserialize(f)
+ return tx
def check_array_result(object_array, to_match, expected):
"""
@@ -103,6 +111,107 @@ class ListTransactionsTest(BitcoinTestFramework):
{"category":"receive","amount":Decimal("0.1")},
{"txid":txid, "account" : "watchonly"} )
+ self.run_rbf_opt_in_test()
+
+ # Check that the opt-in-rbf flag works properly, for sent and received
+ # transactions.
+ def run_rbf_opt_in_test(self):
+ # Check whether a transaction signals opt-in RBF itself
+ def is_opt_in(node, txid):
+ rawtx = node.getrawtransaction(txid, 1)
+ for x in rawtx["vin"]:
+ if x["sequence"] < 0xfffffffe:
+ return True
+ return False
+
+ # Find an unconfirmed output matching a certain txid
+ def get_unconfirmed_utxo_entry(node, txid_to_match):
+ utxo = node.listunspent(0, 0)
+ for i in utxo:
+ if i["txid"] == txid_to_match:
+ return i
+ return None
+
+ # 1. Chain a few transactions that don't opt-in.
+ txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
+ assert(not is_opt_in(self.nodes[0], txid_1))
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+
+ # Tx2 will build off txid_1, still not opting in to RBF.
+ utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
+
+ # Create tx2 using createrawtransaction
+ inputs = [{"txid":utxo_to_use["txid"], "vout":utxo_to_use["vout"]}]
+ outputs = {self.nodes[0].getnewaddress(): 0.999}
+ tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
+ tx2_signed = self.nodes[1].signrawtransaction(tx2)["hex"]
+ txid_2 = self.nodes[1].sendrawtransaction(tx2_signed)
+
+ # ...and check the result
+ assert(not is_opt_in(self.nodes[1], txid_2))
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+
+ # Tx3 will opt-in to RBF
+ utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
+ inputs = [{"txid": txid_2, "vout":utxo_to_use["vout"]}]
+ outputs = {self.nodes[1].getnewaddress(): 0.998}
+ tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
+ tx3_modified = txFromHex(tx3)
+ tx3_modified.vin[0].nSequence = 0
+ tx3 = binascii.hexlify(tx3_modified.serialize()).decode('utf-8')
+ tx3_signed = self.nodes[0].signrawtransaction(tx3)['hex']
+ txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
+
+ assert(is_opt_in(self.nodes[0], txid_3))
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+
+ # Tx4 will chain off tx3. Doesn't signal itself, but depends on one
+ # that does.
+ utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
+ inputs = [{"txid": txid_3, "vout":utxo_to_use["vout"]}]
+ outputs = {self.nodes[0].getnewaddress(): 0.997}
+ tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
+ tx4_signed = self.nodes[1].signrawtransaction(tx4)["hex"]
+ txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
+
+ assert(not is_opt_in(self.nodes[1], txid_4))
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+
+ # Replace tx3, and check that tx4 becomes unknown
+ tx3_b = tx3_modified
+ tx3_b.vout[0].nValue -= 0.004*100000000 # bump the fee
+ tx3_b = binascii.hexlify(tx3_b.serialize()).decode('utf-8')
+ tx3_b_signed = self.nodes[0].signrawtransaction(tx3_b)['hex']
+ txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
+ assert(is_opt_in(self.nodes[0], txid_3b))
+
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+
+ # Check gettransaction as well:
+ for n in self.nodes[0:2]:
+ assert_equal(n.gettransaction(txid_1)["bip125-replaceable"], "no")
+ assert_equal(n.gettransaction(txid_2)["bip125-replaceable"], "no")
+ assert_equal(n.gettransaction(txid_3)["bip125-replaceable"], "yes")
+ assert_equal(n.gettransaction(txid_3b)["bip125-replaceable"], "yes")
+ assert_equal(n.gettransaction(txid_4)["bip125-replaceable"], "unknown")
+
+ # After mining a transaction, it's no longer BIP125-replaceable
+ self.nodes[0].generate(1)
+ assert(txid_3b not in self.nodes[0].getrawmempool())
+ assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no")
+ assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown")
+
+
if __name__ == '__main__':
ListTransactionsTest().main()
diff --git a/share/setup.nsi.in b/share/setup.nsi.in
index 6c0e895bb1..62db88c271 100644
--- a/share/setup.nsi.in
+++ b/share/setup.nsi.in
@@ -7,7 +7,7 @@ SetCompressor /SOLID lzma
!define REGKEY "SOFTWARE\$(^Name)"
!define VERSION @CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@.@CLIENT_VERSION_REVISION@
!define COMPANY "Bitcoin Core project"
-!define URL http://www.bitcoin.org/
+!define URL https://bitcoincore.org/
# MUI Symbol Definitions
!define MUI_ICON "@abs_top_srcdir@/share/pixmaps/bitcoin.ico"
diff --git a/src/Makefile.am b/src/Makefile.am
index 5da1a873de..5d7fbb13d2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -122,6 +122,7 @@ BITCOIN_CORE_H = \
noui.h \
policy/fees.h \
policy/policy.h \
+ policy/rbf.h \
pow.h \
prevector.h \
primitives/block.h \
@@ -239,6 +240,7 @@ libbitcoin_wallet_a_SOURCES = \
wallet/wallet.cpp \
wallet/wallet_ismine.cpp \
wallet/walletdb.cpp \
+ policy/rbf.cpp \
$(BITCOIN_CORE_H)
# crypto primitives library
diff --git a/src/init.cpp b/src/init.cpp
index 53b77775ac..363575f236 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -367,6 +367,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy"));
strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), DEFAULT_PERMIT_BAREMULTISIG));
+ strUsage += HelpMessageOpt("-permitrbf", strprintf(_("Permit transaction replacement (default: %u)"), DEFAULT_PERMIT_REPLACEMENT));
strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with bloom filters (default: %u)"), 1));
if (showDebug)
strUsage += HelpMessageOpt("-enforcenodebloom", strprintf("Enforce minimum protocol version to limit use of bloom filters (default: %u)", 0));
@@ -1015,6 +1016,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (GetBoolArg("-peerbloomfilters", true))
nLocalServices |= NODE_BLOOM;
+ fPermitReplacement = GetBoolArg("-permitrbf", DEFAULT_PERMIT_REPLACEMENT);
+
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
// Initialize elliptic curve code
diff --git a/src/main.cpp b/src/main.cpp
index ee657d997b..d1b0fbac2c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -75,6 +75,7 @@ bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
size_t nCoinCacheUsage = 5000 * 300;
uint64_t nPruneTarget = 0;
bool fAlerts = DEFAULT_ALERTS;
+bool fPermitReplacement = DEFAULT_PERMIT_REPLACEMENT;
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying, mining and transaction creation) */
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
@@ -865,12 +866,15 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// unconfirmed ancestors anyway; doing otherwise is hopelessly
// insecure.
bool fReplacementOptOut = true;
- BOOST_FOREACH(const CTxIn &txin, ptxConflicting->vin)
+ if (fPermitReplacement)
{
- if (txin.nSequence < std::numeric_limits<unsigned int>::max()-1)
+ BOOST_FOREACH(const CTxIn &txin, ptxConflicting->vin)
{
- fReplacementOptOut = false;
- break;
+ if (txin.nSequence < std::numeric_limits<unsigned int>::max()-1)
+ {
+ fReplacementOptOut = false;
+ break;
+ }
}
}
if (fReplacementOptOut)
diff --git a/src/main.h b/src/main.h
index cefaedabf5..d3137c371d 100644
--- a/src/main.h
+++ b/src/main.h
@@ -106,6 +106,8 @@ static const bool DEFAULT_TXINDEX = false;
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
static const bool DEFAULT_TESTSAFEMODE = false;
+/** Default for -permitrbf */
+static const bool DEFAULT_PERMIT_REPLACEMENT = true;
/** Maximum number of headers to announce when relaying blocks with headers message.*/
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8;
@@ -137,6 +139,7 @@ extern bool fCheckpointsEnabled;
extern size_t nCoinCacheUsage;
extern CFeeRate minRelayTxFee;
extern bool fAlerts;
+extern bool fPermitReplacement;
/** Best header we've seen so far (used for getheaders queries' starting points). */
extern CBlockIndex *pindexBestHeader;
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 273a482fa1..c92a249c17 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -135,45 +135,20 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
const CScript& prevScript = prev.scriptPubKey;
if (!Solver(prevScript, whichType, vSolutions))
return false;
- int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
- if (nArgsExpected < 0)
- return false;
-
- // Transactions with extra stuff in their scriptSigs are
- // non-standard. Note that this EvalScript() call will
- // be quick, because if there are any operations
- // beside "push data" in the scriptSig
- // IsStandardTx() will have already returned false
- // and this method isn't called.
- std::vector<std::vector<unsigned char> > stack;
- if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
- return false;
if (whichType == TX_SCRIPTHASH)
{
+ std::vector<std::vector<unsigned char> > stack;
+ // convert the scriptSig into a stack, so we can inspect the redeemScript
+ if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
+ return false;
if (stack.empty())
return false;
CScript subscript(stack.back().begin(), stack.back().end());
- std::vector<std::vector<unsigned char> > vSolutions2;
- txnouttype whichType2;
- if (Solver(subscript, whichType2, vSolutions2))
- {
- int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2);
- if (tmpExpected < 0)
- return false;
- nArgsExpected += tmpExpected;
- }
- else
- {
- // Any other Script with less than 15 sigops OK:
- unsigned int sigops = subscript.GetSigOpCount(true);
- // ... extra data left on the stack after execution is OK, too:
- return (sigops <= MAX_P2SH_SIGOPS);
+ if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
+ return false;
}
}
-
- if (stack.size() != (unsigned int)nArgsExpected)
- return false;
}
return true;
diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp
new file mode 100644
index 0000000000..98b1a1ba4c
--- /dev/null
+++ b/src/policy/rbf.cpp
@@ -0,0 +1,46 @@
+// Copyright (c) 2016 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "policy/rbf.h"
+
+bool SignalsOptInRBF(const CTransaction &tx)
+{
+ BOOST_FOREACH(const CTxIn &txin, tx.vin) {
+ if (txin.nSequence < std::numeric_limits<unsigned int>::max()-1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool)
+{
+ AssertLockHeld(pool.cs);
+
+ CTxMemPool::setEntries setAncestors;
+
+ // First check the transaction itself.
+ if (SignalsOptInRBF(entry.GetTx())) {
+ return true;
+ }
+
+ // If this transaction is not in our mempool, then we can't be sure
+ // we will know about all its inputs.
+ if (!pool.exists(entry.GetTx().GetHash())) {
+ throw std::runtime_error("Cannot determine RBF opt-in signal for non-mempool transaction\n");
+ }
+
+ // If all the inputs have nSequence >= maxint-1, it still might be
+ // signaled for RBF if any unconfirmed parents have signaled.
+ uint64_t noLimit = std::numeric_limits<uint64_t>::max();
+ std::string dummy;
+ pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
+
+ BOOST_FOREACH(CTxMemPool::txiter it, setAncestors) {
+ if (SignalsOptInRBF(it->GetTx())) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/policy/rbf.h b/src/policy/rbf.h
new file mode 100644
index 0000000000..925ce0d9bd
--- /dev/null
+++ b/src/policy/rbf.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2016 The Bitcoin developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_POLICY_RBF_H
+#define BITCOIN_POLICY_RBF_H
+
+#include "txmempool.h"
+
+// Check whether the sequence numbers on this transaction are signaling
+// opt-in to replace-by-fee, according to BIP 125
+bool SignalsOptInRBF(const CTransaction &tx);
+
+// Determine whether an in-mempool transaction is signaling opt-in to RBF
+// according to BIP 125
+// This involves checking sequence numbers of the transaction, as well
+// as the sequence numbers of all in-mempool ancestors.
+bool IsRBFOptIn(const CTxMemPoolEntry &entry, CTxMemPool &pool);
+
+#endif // BITCOIN_POLICY_RBF_H
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4c869b9ac5..be589c815c 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -472,7 +472,11 @@ void RPCConsole::clear()
// Set default style sheet
QFontInfo fixedFontInfo(GUIUtil::fixedPitchFont());
// Try to make fixed font adequately large on different OS
+#ifdef WIN32
+ QString ptSize = QString("%1pt").arg(QFontInfo(QFont()).pointSize() * 10 / 8);
+#else
QString ptSize = QString("%1pt").arg(QFontInfo(QFont()).pointSize() * 8.5 / 9);
+#endif
ui->messagesWidget->document()->setDefaultStyleSheet(
QString(
"table { }"
diff --git a/src/script/standard.cpp b/src/script/standard.cpp
index 30935768ac..67b6af327a 100644
--- a/src/script/standard.cpp
+++ b/src/script/standard.cpp
@@ -161,27 +161,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
return false;
}
-int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
-{
- switch (t)
- {
- case TX_NONSTANDARD:
- case TX_NULL_DATA:
- return -1;
- case TX_PUBKEY:
- return 1;
- case TX_PUBKEYHASH:
- return 2;
- case TX_MULTISIG:
- if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
- return -1;
- return vSolutions[0][0] + 1;
- case TX_SCRIPTHASH:
- return 1; // doesn't include args needed by the script
- }
- return -1;
-}
-
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
vector<valtype> vSolutions;
diff --git a/src/script/standard.h b/src/script/standard.h
index 6bac6e4097..64bf010ec1 100644
--- a/src/script/standard.h
+++ b/src/script/standard.h
@@ -71,7 +71,6 @@ typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
const char* GetTxnOutputType(txnouttype t);
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
-int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index 7bd4b8441b..28b85e8d29 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -346,15 +346,6 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
// 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U);
- // Make sure adding crap to the scriptSigs makes them non-standard:
- for (int i = 0; i < 3; i++)
- {
- CScript t = txTo.vin[i].scriptSig;
- txTo.vin[i].scriptSig = (CScript() << 11) + t;
- BOOST_CHECK(!::AreInputsStandard(txTo, coins));
- txTo.vin[i].scriptSig = t;
- }
-
CMutableTransaction txToNonStd1;
txToNonStd1.vout.resize(1);
txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp
index 3dca7ea0f7..c27f194b55 100644
--- a/src/test/transaction_tests.cpp
+++ b/src/test/transaction_tests.cpp
@@ -310,14 +310,6 @@ BOOST_AUTO_TEST_CASE(test_Get)
BOOST_CHECK(AreInputsStandard(t1, coins));
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
-
- // Adding extra junk to the scriptSig should make it non-standard:
- t1.vin[0].scriptSig << OP_11;
- BOOST_CHECK(!AreInputsStandard(t1, coins));
-
- // ... as should not having enough:
- t1.vin[0].scriptSig = CScript();
- BOOST_CHECK(!AreInputsStandard(t1, coins));
}
BOOST_AUTO_TEST_CASE(test_IsStandard)
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index d18250b76f..50b0f40a6a 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -205,7 +205,7 @@ bool CDBEnv::Salvage(const std::string& strFile, bool fAggressive, std::vector<C
std::string keyHex, valueHex;
while (!strDump.eof() && keyHex != "DATA=END") {
getline(strDump, keyHex);
- if (keyHex != "DATA_END") {
+ if (keyHex != "DATA=END") {
getline(strDump, valueHex);
vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
}
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index e68d646096..f7f1467631 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -11,6 +11,7 @@
#include "main.h"
#include "net.h"
#include "netbase.h"
+#include "policy/rbf.h"
#include "rpcserver.h"
#include "timedata.h"
#include "util.h"
@@ -76,6 +77,23 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
entry.push_back(Pair("walletconflicts", conflicts));
entry.push_back(Pair("time", wtx.GetTxTime()));
entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
+
+ // Add opt-in RBF status
+ std::string rbfStatus = "no";
+ if (confirms <= 0) {
+ LOCK(mempool.cs);
+ if (!mempool.exists(hash)) {
+ if (SignalsOptInRBF(wtx)) {
+ rbfStatus = "yes";
+ } else {
+ rbfStatus = "unknown";
+ }
+ } else if (IsRBFOptIn(*mempool.mapTx.find(hash), mempool)) {
+ rbfStatus = "yes";
+ }
+ }
+ entry.push_back(Pair("bip125-replaceable", rbfStatus));
+
BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
entry.push_back(Pair(item.first, item.second));
}
@@ -1439,6 +1457,8 @@ UniValue listtransactions(const UniValue& params, bool fHelp)
" \"otheraccount\": \"accountname\", (string) For the 'move' category of transactions, the account the funds came \n"
" from (for receiving funds, positive amounts), or went to (for sending funds,\n"
" negative amounts).\n"
+ " \"bip125-replaceable\": \"yes|no|unknown\" (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
+ " may be unknown for unconfirmed transactions not in the mempool\n"
" }\n"
"]\n"
@@ -1707,6 +1727,8 @@ UniValue gettransaction(const UniValue& params, bool fHelp)
" \"txid\" : \"transactionid\", (string) The transaction id.\n"
" \"time\" : ttt, (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
" \"timereceived\" : ttt, (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
+ " \"bip125-replaceable\": \"yes|no|unknown\" (string) Whether this transaction could be replaced due to BIP125 (replace-by-fee);\n"
+ " may be unknown for unconfirmed transactions not in the mempool\n"
" \"details\" : [\n"
" {\n"
" \"account\" : \"accountname\", (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"