Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backports 0.18 pr11 #4289

Merged
merged 9 commits into from
Jul 28, 2021
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,15 @@ after_success:
DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
GOAL="install"
BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CXXFLAGS=\"-g0 -O2\""
# x86_64 Linux (xenial, no depends, only system libs)
- stage: test
env: >-
HOST=x86_64-unknown-linux-gnu
DOCKER_NAME_TAG=ubuntu:16.04
PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
NO_DEPENDS=1
GOAL="install"
BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER"
# x86_64 Linux (no depends, only system libs)
- stage: test
env: >-
Expand Down
11 changes: 7 additions & 4 deletions src/httpserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,13 @@ static bool ThreadHTTP(struct event_base* base)
/** Bind HTTP server to specified addresses */
static bool HTTPBindAddresses(struct evhttp* http)
{
int defaultPort = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
int http_port = gArgs.GetArg("-rpcport", BaseParams().RPCPort());
std::vector<std::pair<std::string, uint16_t> > endpoints;

// Determine what addresses to bind to
if (!(gArgs.IsArgSet("-rpcallowip") && gArgs.IsArgSet("-rpcbind"))) { // Default to loopback if not allowing external IPs
endpoints.push_back(std::make_pair("::1", defaultPort));
endpoints.push_back(std::make_pair("127.0.0.1", defaultPort));
endpoints.push_back(std::make_pair("::1", http_port));
endpoints.push_back(std::make_pair("127.0.0.1", http_port));
if (gArgs.IsArgSet("-rpcallowip")) {
LogPrintf("WARNING: option -rpcallowip was specified without -rpcbind; this doesn't usually make sense\n");
}
Expand All @@ -316,11 +316,14 @@ static bool HTTPBindAddresses(struct evhttp* http)
}
} else if (gArgs.IsArgSet("-rpcbind")) { // Specific bind address
for (const std::string& strRPCBind : gArgs.GetArgs("-rpcbind")) {
int port = defaultPort;
int port = http_port;
std::string host;
SplitHostPort(strRPCBind, port, host);
endpoints.push_back(std::make_pair(host, port));
}
} else { // No specific bind address specified, bind to any
endpoints.push_back(std::make_pair("::", http_port));
endpoints.push_back(std::make_pair("0.0.0.0", http_port));
}

// Bind addresses
Expand Down
8 changes: 2 additions & 6 deletions src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,7 @@ class WalletImpl : public Wallet
return result;
}
bool tryGetTxStatus(const uint256& txid,
interfaces::WalletTxStatus& tx_status,
int64_t& adjusted_time) override
interfaces::WalletTxStatus& tx_status) override
{
TRY_LOCK(::cs_main, locked_chain);
if (!locked_chain) {
Expand All @@ -357,22 +356,19 @@ class WalletImpl : public Wallet
if (mi == m_wallet.mapWallet.end()) {
return false;
}
adjusted_time = GetAdjustedTime();
tx_status = MakeWalletTxStatus(mi->second);
return true;
}
WalletTx getWalletTxDetails(const uint256& txid,
WalletTxStatus& tx_status,
WalletOrderForm& order_form,
bool& in_mempool,
int& num_blocks,
int64_t& adjusted_time) override
int& num_blocks) override
{
LOCK2(::cs_main, m_wallet.cs_wallet);
auto mi = m_wallet.mapWallet.find(txid);
if (mi != m_wallet.mapWallet.end()) {
num_blocks = ::chainActive.Height();
adjusted_time = GetAdjustedTime();
in_mempool = mi->second.InMempool();
order_form = mi->second.vOrderForm;
tx_status = MakeWalletTxStatus(mi->second);
Expand Down
6 changes: 2 additions & 4 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,14 @@ class Wallet

//! Try to get updated status for a particular transaction, if possible without blocking.
virtual bool tryGetTxStatus(const uint256& txid,
WalletTxStatus& tx_status,
int64_t& adjusted_time) = 0;
WalletTxStatus& tx_status) = 0;

//! Get transaction details.
virtual WalletTx getWalletTxDetails(const uint256& txid,
WalletTxStatus& tx_status,
WalletOrderForm& order_form,
bool& in_mempool,
int& num_blocks,
int64_t& adjusted_time) = 0;
int& num_blocks) = 0;

// Get the number of coinjoin rounds an output went through
virtual int getRealOutpointCoinJoinRounds(const COutPoint& outpoint) = 0;
Expand Down
7 changes: 3 additions & 4 deletions src/qt/transactiondesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <stdint.h>
#include <string>

QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks, int64_t adjustedTime)
QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks)
{
if (!status.is_final)
{
Expand Down Expand Up @@ -61,11 +61,10 @@ QString TransactionDesc::FormatTxStatus(const interfaces::WalletTx& wtx, const i
QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit)
{
int numBlocks;
int64_t adjustedTime;
interfaces::WalletTxStatus status;
interfaces::WalletOrderForm orderForm;
bool inMempool;
interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks, adjustedTime);
interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks);

QString strHTML;

Expand All @@ -77,7 +76,7 @@ QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wall
CAmount nDebit = wtx.debit;
CAmount nNet = nCredit - nDebit;

strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks, adjustedTime);
strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks);
strHTML += "<br>";

strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>";
Expand Down
2 changes: 1 addition & 1 deletion src/qt/transactiondesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class TransactionDesc: public QObject
private:
TransactionDesc() {}

static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks, int64_t adjustedTime);
static QString FormatTxStatus(const interfaces::WalletTx& wtx, const interfaces::WalletTxStatus& status, bool inMempool, int numBlocks);
};

#endif // BITCOIN_QT_TRANSACTIONDESC_H
2 changes: 1 addition & 1 deletion src/qt/transactionrecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(interfaces::Wal
return parts;
}

void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t adjustedTime, int chainLockHeight)
void TransactionRecord::updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int chainLockHeight)
{
// Determine transaction status

Expand Down
2 changes: 1 addition & 1 deletion src/qt/transactionrecord.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class TransactionRecord

/** Update status from core wallet tx.
*/
void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int64_t adjustedTime, int chainLockHeight);
void updateStatus(const interfaces::WalletTxStatus& wtx, int numBlocks, int chainLockHeight);

/** Return whether a status update is needed.
*/
Expand Down
5 changes: 2 additions & 3 deletions src/qt/transactiontablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,8 @@ class TransactionTablePriv
// try to update the status of this transaction from the wallet.
// Otherwise, simply re-use the cached status.
interfaces::WalletTxStatus wtx;
int64_t adjustedTime;
if (rec->statusUpdateNeeded(numBlocks, parent->getChainLockHeight()) && wallet.tryGetTxStatus(rec->hash, wtx, adjustedTime)) {
rec->updateStatus(wtx, numBlocks, adjustedTime, parent->getChainLockHeight());
if (rec->statusUpdateNeeded(numBlocks, parent->getChainLockHeight()) && wallet.tryGetTxStatus(rec->hash, wtx)) {
rec->updateStatus(wtx, numBlocks, parent->getChainLockHeight());
}
return rec;
}
Expand Down
30 changes: 27 additions & 3 deletions src/script/sign.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,14 +276,18 @@ struct PSBTInput
template <typename Stream>
inline void Unserialize(Stream& s) {
// Read loop
bool found_sep = false;
while(!s.empty()) {
// Read
std::vector<unsigned char> key;
s >> key;

// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
if (key.empty()) return;
if (key.empty()) {
found_sep = true;
break;
}

// First byte of key is the type
unsigned char type = key[0];
Expand Down Expand Up @@ -366,6 +370,10 @@ struct PSBTInput
break;
}
}

if (!found_sep) {
throw std::ios_base::failure("Separator is missing at the end of an input map");
}
}

template <typename Stream>
Expand Down Expand Up @@ -412,14 +420,18 @@ struct PSBTOutput
template <typename Stream>
inline void Unserialize(Stream& s) {
// Read loop
bool found_sep = false;
while(!s.empty()) {
// Read
std::vector<unsigned char> key;
s >> key;

// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
if (key.empty()) return;
if (key.empty()) {
found_sep = true;
break;
}

// First byte of key is the type
unsigned char type = key[0];
Expand Down Expand Up @@ -454,6 +466,10 @@ struct PSBTOutput
}
}
}

if (!found_sep) {
throw std::ios_base::failure("Separator is missing at the end of an output map");
}
}

template <typename Stream>
Expand Down Expand Up @@ -528,14 +544,18 @@ struct PartiallySignedTransaction
}

// Read global data
bool found_sep = false;
while(!s.empty()) {
// Read
std::vector<unsigned char> key;
s >> key;

// the key is empty if that was actually a separator byte
// This is a special case for key lengths 0 as those are not allowed (except for separator)
if (key.empty()) break;
if (key.empty()) {
found_sep = true;
break;
}

// First byte of key is the type
unsigned char type = key[0];
Expand Down Expand Up @@ -573,6 +593,10 @@ struct PartiallySignedTransaction
}
}

if (!found_sep) {
throw std::ios_base::failure("Separator is missing at the end of the global map");
}

// Make sure that we got an unsigned tx
if (!tx) {
throw std::ios_base::failure("No unsigned transcation was provided");
Expand Down
4 changes: 2 additions & 2 deletions src/test/miner_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ static CBlockIndex CreateBlockIndex(int nHeight)

static bool TestSequenceLocks(const CTransaction &tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
LOCK(mempool.cs);
return CheckSequenceLocks(tx, flags);
LOCK(::mempool.cs);
return CheckSequenceLocks(::mempool, tx, flags);
}

// Test suite for ancestor feerate transaction selection.
Expand Down
2 changes: 1 addition & 1 deletion src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,7 @@ void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMem
const CTransaction& tx = it->GetTx();
LockPoints lp = it->GetLockPoints();
bool validLP = TestLockPointValidity(&lp);
if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(tx, flags, &lp, validLP)) {
if (!CheckFinalTx(tx, flags) || !CheckSequenceLocks(*this, tx, flags, &lp, validLP)) {
// Note if CheckSequenceLocks fails the LockPoints may still be invalid
// So it's critical that we remove the tx and not depend on the LockPoints.
txToRemove.insert(it);
Expand Down
8 changes: 4 additions & 4 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,10 @@ bool TestLockPointValidity(const LockPoints* lp)
return true;
}

bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool useExistingLockPoints)
bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp, bool useExistingLockPoints)
{
AssertLockHeld(cs_main);
AssertLockHeld(mempool.cs);
AssertLockHeld(pool.cs);

CBlockIndex* tip = chainActive.Tip();
assert(tip != nullptr);
Expand All @@ -405,7 +405,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool
}
else {
// pcoinsTip contains the UTXO set for chainActive.Tip()
CCoinsViewMemPool viewMemPool(pcoinsTip.get(), mempool);
CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool);
std::vector<int> prevheights;
prevheights.resize(tx.vin.size());
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
Expand Down Expand Up @@ -738,7 +738,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// be mined yet.
// Must keep pool.cs for this unless we change CheckSequenceLocks to take a
// CoinsViewCache instead of create its own
if (!CheckSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
if (!CheckSequenceLocks(pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp))
return state.DoS(0, false, REJECT_NONSTANDARD, "non-BIP68-final");

CAmount nFees = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ bool TestLockPointValidity(const LockPoints* lp) EXCLUSIVE_LOCKS_REQUIRED(cs_mai
*
* See consensus/consensus.h for flag definitions.
*/
bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool CheckSequenceLocks(const CTxMemPool& pool, const CTransaction& tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

/**
* Closure representing one script verification
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const WalletInitInterface& g_wallet_init_interface = WalletInit();

void WalletInit::AddWalletOptions() const
{
gArgs.AddArg("-avoidpartialspends", strprintf(_("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)"), DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
gArgs.AddArg("-avoidpartialspends", strprintf("Group outputs by address, selecting all or none, instead of selecting on a per-output basis. Privacy is improved as an address is only used once (unless someone sends to it after spending from it), but may result in slightly higher fees as suboptimal coin selection may result due to the added limitation (default: %u)", DEFAULT_AVOIDPARTIALSPENDS), false, OptionsCategory::WALLET);
gArgs.AddArg("-createwalletbackups=<n>", strprintf("Number of automatic wallet backups (default: %u)", nWalletBackups), false, OptionsCategory::WALLET);
gArgs.AddArg("-disablewallet", "Do not load the wallet and disable wallet RPC calls", false, OptionsCategory::WALLET);
gArgs.AddArg("-instantsendnotify=<cmd>", "Execute command when a wallet InstantSend transaction is successfully locked (%s in cmd is replaced by TxID)", false, OptionsCategory::WALLET);
Expand Down
2 changes: 2 additions & 0 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4165,6 +4165,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
" \"ismine\" : true|false, (boolean) If the address is yours or not\n"
" \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n"
" \"isscript\" : true|false, (boolean) If the key is a script\n"
" \"ischange\" : true|false, (boolean) If the address was used for change output\n"
" \"script\" : \"type\" (string, optional) The output script type. Only if \"isscript\" is true and the redeemscript is known. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata\n"
" \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n"
" \"pubkeys\" (string, optional) Array of pubkeys associated with the known redeemscript (only if \"script\" is \"multisig\")\n"
Expand Down Expand Up @@ -4222,6 +4223,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
ret.pushKV("account", pwallet->mapAddressBook[dest].name);
}
}
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
const CKeyMetadata* meta = nullptr;
const CKeyID *key_id = boost::get<CKeyID>(&dest);
if (key_id != nullptr && !key_id->IsNull()) {
Expand Down
9 changes: 7 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,11 @@ CAmount CWallet::GetCredit(const CTxOut& txout, const isminefilter& filter) cons
}

bool CWallet::IsChange(const CTxOut& txout) const
{
return IsChange(txout.scriptPubKey);
}

bool CWallet::IsChange(const CScript& script) const
{
// TODO: fix handling of 'change' outputs. The assumption is that any
// payment to a script that is ours, but is not in the address book
Expand All @@ -1725,10 +1730,10 @@ bool CWallet::IsChange(const CTxOut& txout) const
// a better way of identifying which outputs are 'the send' and which are
// 'the change' will need to be implemented (maybe extend CWalletTx to remember
// which output, if any, was change).
if (::IsMine(*this, txout.scriptPubKey))
if (::IsMine(*this, script))
{
CTxDestination address;
if (!ExtractDestination(txout.scriptPubKey, address))
if (!ExtractDestination(script, address))
return true;

LOCK(cs_wallet);
Expand Down
1 change: 1 addition & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
isminetype IsMine(const CTxOut& txout) const;
CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const;
bool IsChange(const CTxOut& txout) const;
bool IsChange(const CScript& script) const;
CAmount GetChange(const CTxOut& txout) const;
bool IsMine(const CTransaction& tx) const;
/** should probably be renamed to IsRelevantToMe */
Expand Down
Loading