mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 04:22:55 +01:00
Merge pull request #3540 from PastaPastaPasta/backports-0.17-pr8
Backports 0.17 pr8
This commit is contained in:
commit
c59dafb708
@ -43,18 +43,28 @@ class TestSecurityChecks(unittest.TestCase):
|
||||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE']),
|
||||
(0, ''))
|
||||
|
||||
def test_PE(self):
|
||||
def test_32bit_PE(self):
|
||||
source = 'test1.c'
|
||||
executable = 'test1.exe'
|
||||
cc = 'i686-w64-mingw32-gcc'
|
||||
write_testcode(source)
|
||||
|
||||
self.assertEqual(call_security_check(cc, source, executable, []),
|
||||
(1, executable+': failed PIE NX'))
|
||||
(1, executable+': failed DYNAMIC_BASE NX'))
|
||||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat']),
|
||||
(1, executable+': failed PIE'))
|
||||
(1, executable+': failed DYNAMIC_BASE'))
|
||||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase']),
|
||||
(0, ''))
|
||||
def test_64bit_PE(self):
|
||||
source = 'test1.c'
|
||||
executable = 'test1.exe'
|
||||
cc = 'x86_64-w64-mingw32-gcc'
|
||||
write_testcode(source)
|
||||
|
||||
self.assertEqual(call_security_check(cc, source, executable, []), (1, executable+': failed DYNAMIC_BASE NX\n'+executable+': warning HIGH_ENTROPY_VA'))
|
||||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat']), (1, executable+': failed DYNAMIC_BASE\n'+executable+': warning HIGH_ENTROPY_VA'))
|
||||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase']), (0, executable+': warning HIGH_ENTROPY_VA'))
|
||||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase','-Wl,--high-entropy-va']), (0, ''))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -7,8 +7,8 @@
|
||||
#define BITCOIN_CHAIN_H
|
||||
|
||||
#include <arith_uint256.h>
|
||||
#include <consensus/params.h>
|
||||
#include <primitives/block.h>
|
||||
#include <pow.h>
|
||||
#include <tinyformat.h>
|
||||
#include <uint256.h>
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <consensus/merkle.h>
|
||||
#include <consensus/validation.h>
|
||||
#include <hash.h>
|
||||
#include <validation.h>
|
||||
#include <net.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <policy/policy.h>
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <primitives/block.h>
|
||||
#include <txmempool.h>
|
||||
#include <validation.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
@ -171,7 +172,7 @@ private:
|
||||
/** Add transactions based on feerate including unconfirmed ancestors
|
||||
* Increments nPackagesSelected / nDescendantsUpdated with corresponding
|
||||
* statistics from the package selection (for logging statistics). */
|
||||
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated);
|
||||
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
|
||||
|
||||
// helper functions for addPackageTxs()
|
||||
/** Remove confirmed (inBlock) entries from given set */
|
||||
@ -185,13 +186,13 @@ private:
|
||||
bool TestPackageTransactions(const CTxMemPool::setEntries& package);
|
||||
/** Return true if given transaction from mapTx has already been evaluated,
|
||||
* or if the transaction's cached data in mapTx is incorrect. */
|
||||
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx);
|
||||
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
|
||||
/** Sort the package in an order that is valid to appear in a block */
|
||||
void SortForBlock(const CTxMemPool::setEntries& package, std::vector<CTxMemPool::txiter>& sortedEntries);
|
||||
/** Add descendants of given transactions to mapModifiedTx with ancestor
|
||||
* state updated assuming given transactions are inBlock. Returns number
|
||||
* of updated descendants. */
|
||||
int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx);
|
||||
int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
|
||||
};
|
||||
|
||||
/** Modify the extranonce in a block */
|
||||
|
@ -197,7 +197,7 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
|
||||
amount = new AmountSpinBox(this);
|
||||
amount->setLocale(QLocale::c());
|
||||
amount->installEventFilter(this);
|
||||
amount->setMaximumWidth(170);
|
||||
amount->setMaximumWidth(240);
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->addWidget(amount);
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <sys/random.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYSCTL_ARND
|
||||
#include <utilstrencodings.h> // for ARRAYLEN
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
|
@ -25,10 +25,10 @@
|
||||
#include <memory> // for unique_ptr
|
||||
#include <unordered_map>
|
||||
|
||||
static bool fRPCRunning = false;
|
||||
static bool fRPCInWarmup = true;
|
||||
static std::string rpcWarmupStatus("RPC server started");
|
||||
static CCriticalSection cs_rpcWarmup;
|
||||
static bool fRPCRunning = false;
|
||||
static bool fRPCInWarmup GUARDED_BY(cs_rpcWarmup) = true;
|
||||
static std::string rpcWarmupStatus GUARDED_BY(cs_rpcWarmup) = "RPC server started";
|
||||
/* Timer-creating functions */
|
||||
static RPCTimerInterface* timerInterface = nullptr;
|
||||
/* Map of name to timer. */
|
||||
|
@ -95,8 +95,8 @@ private:
|
||||
CScheduler *m_pscheduler;
|
||||
|
||||
CCriticalSection m_cs_callbacks_pending;
|
||||
std::list<std::function<void (void)>> m_callbacks_pending;
|
||||
bool m_are_callbacks_running = false;
|
||||
std::list<std::function<void (void)>> m_callbacks_pending GUARDED_BY(m_cs_callbacks_pending);
|
||||
bool m_are_callbacks_running GUARDED_BY(m_cs_callbacks_pending) = false;
|
||||
|
||||
void MaybeScheduleProcessQueue();
|
||||
void ProcessQueue();
|
||||
|
19
src/sync.cpp
19
src/sync.cpp
@ -72,7 +72,7 @@ struct LockData {
|
||||
std::mutex dd_mutex;
|
||||
} static lockdata;
|
||||
|
||||
static thread_local std::unique_ptr<LockStack> lockstack;
|
||||
static thread_local LockStack g_lockstack;
|
||||
|
||||
static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
|
||||
{
|
||||
@ -107,21 +107,18 @@ static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch,
|
||||
|
||||
static void push_lock(void* c, const CLockLocation& locklocation)
|
||||
{
|
||||
if (!lockstack)
|
||||
lockstack.reset(new LockStack);
|
||||
|
||||
std::lock_guard<std::mutex> lock(lockdata.dd_mutex);
|
||||
|
||||
lockstack->push_back(std::make_pair(c, locklocation));
|
||||
g_lockstack.push_back(std::make_pair(c, locklocation));
|
||||
|
||||
for (const std::pair<void*, CLockLocation> & i : (*lockstack)) {
|
||||
for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
|
||||
if (i.first == c)
|
||||
break;
|
||||
|
||||
std::pair<void*, void*> p1 = std::make_pair(i.first, c);
|
||||
if (lockdata.lockorders.count(p1))
|
||||
continue;
|
||||
lockdata.lockorders[p1] = (*lockstack);
|
||||
lockdata.lockorders[p1] = g_lockstack;
|
||||
|
||||
std::pair<void*, void*> p2 = std::make_pair(c, i.first);
|
||||
lockdata.invlockorders.insert(p2);
|
||||
@ -132,7 +129,7 @@ static void push_lock(void* c, const CLockLocation& locklocation)
|
||||
|
||||
static void pop_lock()
|
||||
{
|
||||
(*lockstack).pop_back();
|
||||
g_lockstack.pop_back();
|
||||
}
|
||||
|
||||
void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
|
||||
@ -148,14 +145,14 @@ void LeaveCritical()
|
||||
std::string LocksHeld()
|
||||
{
|
||||
std::string result;
|
||||
for (const std::pair<void*, CLockLocation> & i : *lockstack)
|
||||
for (const std::pair<void*, CLockLocation>& i : g_lockstack)
|
||||
result += i.second.ToString() + std::string("\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
|
||||
{
|
||||
for (const std::pair<void*, CLockLocation> & i : *lockstack)
|
||||
for (const std::pair<void*, CLockLocation>& i : g_lockstack)
|
||||
if (i.first == cs)
|
||||
return;
|
||||
fprintf(stderr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
|
||||
@ -164,7 +161,7 @@ void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine,
|
||||
|
||||
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
|
||||
{
|
||||
for (const std::pair<void*, CLockLocation>& i : *lockstack) {
|
||||
for (const std::pair<void*, CLockLocation>& i : g_lockstack) {
|
||||
if (i.first == cs) {
|
||||
fprintf(stderr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
|
||||
abort();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <blockencodings.h>
|
||||
#include <consensus/merkle.h>
|
||||
#include <chainparams.h>
|
||||
#include <pow.h>
|
||||
#include <random.h>
|
||||
|
||||
#include <test/test_dash.h>
|
||||
|
@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
|
||||
}
|
||||
|
||||
template<typename name>
|
||||
void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder)
|
||||
void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(pool.size(), sortedOrder.size());
|
||||
typename CTxMemPool::indexed_transaction_set::index<name>::type::iterator it = pool.mapTx.get<name>().begin();
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <masternode/masternode-payments.h>
|
||||
#include <miner.h>
|
||||
#include <policy/policy.h>
|
||||
#include <pow.h>
|
||||
#include <pubkey.h>
|
||||
#include <script/standard.h>
|
||||
#include <txmempool.h>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <validation.h>
|
||||
#include <miner.h>
|
||||
#include <net_processing.h>
|
||||
#include <pow.h>
|
||||
#include <ui_interface.h>
|
||||
#include <streams.h>
|
||||
#include <rpc/server.h>
|
||||
|
@ -3,10 +3,18 @@
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
#include <test/test_dash.h>
|
||||
#include <torcontrol.cpp>
|
||||
#include <torcontrol.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
|
||||
std::pair<std::string, std::string> SplitTorReplyLine(const std::string& s);
|
||||
std::map<std::string, std::string> ParseTorReplyMapping(const std::string& s);
|
||||
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(torcontrol_tests, BasicTestingSetup)
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
|
||||
static CCriticalSection cs_nTimeOffset;
|
||||
static int64_t nTimeOffset = 0;
|
||||
static int64_t nTimeOffset GUARDED_BY(cs_nTimeOffset) = 0;
|
||||
|
||||
/**
|
||||
* "Never go to sea with two chronometers; take one or three."
|
||||
|
@ -251,7 +251,7 @@ bool TorControlConnection::Command(const std::string &cmd, const ReplyHandlerCB&
|
||||
* Grammar is implicitly defined in https://spec.torproject.org/control-spec by
|
||||
* the server reply formats for PROTOCOLINFO (S3.21) and AUTHCHALLENGE (S3.24).
|
||||
*/
|
||||
static std::pair<std::string,std::string> SplitTorReplyLine(const std::string &s)
|
||||
std::pair<std::string,std::string> SplitTorReplyLine(const std::string &s)
|
||||
{
|
||||
size_t ptr=0;
|
||||
std::string type;
|
||||
@ -270,7 +270,7 @@ static std::pair<std::string,std::string> SplitTorReplyLine(const std::string &s
|
||||
* the server reply formats for PROTOCOLINFO (S3.21), AUTHCHALLENGE (S3.24),
|
||||
* and ADD_ONION (S3.27). See also sections 2.1 and 2.3.
|
||||
*/
|
||||
static std::map<std::string,std::string> ParseTorReplyMapping(const std::string &s)
|
||||
std::map<std::string,std::string> ParseTorReplyMapping(const std::string &s)
|
||||
{
|
||||
std::map<std::string,std::string> mapping;
|
||||
size_t ptr=0;
|
||||
|
@ -1012,6 +1012,7 @@ static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& m
|
||||
|
||||
void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||
{
|
||||
LOCK(cs);
|
||||
if (nCheckFrequency == 0)
|
||||
return;
|
||||
|
||||
@ -1026,7 +1027,6 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
|
||||
const int64_t spendheight = GetSpendHeight(mempoolDuplicate);
|
||||
|
||||
LOCK(cs);
|
||||
std::list<const CTxMemPoolEntry*> waitingOnDependants;
|
||||
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
|
||||
unsigned int i = 0;
|
||||
|
@ -442,7 +442,7 @@ public:
|
||||
class CTxMemPool
|
||||
{
|
||||
private:
|
||||
uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check.
|
||||
uint32_t nCheckFrequency GUARDED_BY(cs); //!< Value n means that n times in 2^32 we check.
|
||||
unsigned int nTransactionsUpdated; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
|
||||
CBlockPolicyEstimator* minerPolicyEstimator;
|
||||
|
||||
@ -486,7 +486,7 @@ public:
|
||||
> indexed_transaction_set;
|
||||
|
||||
mutable CCriticalSection cs;
|
||||
indexed_transaction_set mapTx;
|
||||
indexed_transaction_set mapTx GUARDED_BY(cs);
|
||||
|
||||
typedef indexed_transaction_set::nth_index<0>::type::iterator txiter;
|
||||
std::vector<std::pair<uint256, txiter> > vTxHashes; //!< All tx hashes/entries in mapTx, in random order
|
||||
@ -498,8 +498,8 @@ public:
|
||||
};
|
||||
typedef std::set<txiter, CompareIteratorByHash> setEntries;
|
||||
|
||||
const setEntries & GetMemPoolParents(txiter entry) const;
|
||||
const setEntries & GetMemPoolChildren(txiter entry) const;
|
||||
const setEntries & GetMemPoolParents(txiter entry) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
const setEntries & GetMemPoolChildren(txiter entry) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
private:
|
||||
typedef std::map<txiter, setEntries, CompareIteratorByHash> cacheMap;
|
||||
|
||||
@ -535,7 +535,7 @@ private:
|
||||
std::vector<indexed_transaction_set::const_iterator> GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
public:
|
||||
indirectmap<COutPoint, const CTransaction*> mapNextTx;
|
||||
indirectmap<COutPoint, const CTransaction*> mapNextTx GUARDED_BY(cs);
|
||||
std::map<uint256, CAmount> mapDeltas;
|
||||
|
||||
/** Create a new CTxMemPool.
|
||||
@ -549,7 +549,7 @@ public:
|
||||
* check does nothing.
|
||||
*/
|
||||
void check(const CCoinsViewCache *pcoins) const;
|
||||
void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = static_cast<uint32_t>(dFrequency * 4294967295.0); }
|
||||
void setSanityCheck(double dFrequency = 1.0) { LOCK(cs); nCheckFrequency = static_cast<uint32_t>(dFrequency * 4294967295.0); }
|
||||
|
||||
// addUnchecked must updated state for all ancestors of a given transaction,
|
||||
// to track size/count of descendant transactions. First version of
|
||||
@ -582,7 +582,7 @@ public:
|
||||
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight);
|
||||
|
||||
void clear();
|
||||
void _clear(); //lock free
|
||||
void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs); //lock free
|
||||
bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb);
|
||||
void queryHashes(std::vector<uint256>& vtxid);
|
||||
bool isSpent(const COutPoint& outpoint);
|
||||
@ -635,7 +635,7 @@ public:
|
||||
/** Populate setDescendants with all in-mempool descendants of hash.
|
||||
* Assumes that setDescendants includes all in-mempool descendants of anything
|
||||
* already in it. */
|
||||
void CalculateDescendants(txiter it, setEntries &setDescendants);
|
||||
void CalculateDescendants(txiter it, setEntries &setDescendants) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
/** The minimum fee to get into the mempool, which may itself not be enough
|
||||
* for larger-sized transactions.
|
||||
@ -702,17 +702,17 @@ private:
|
||||
*/
|
||||
void UpdateForDescendants(txiter updateIt,
|
||||
cacheMap &cachedDescendants,
|
||||
const std::set<uint256> &setExclude);
|
||||
const std::set<uint256> &setExclude) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
/** Update ancestors of hash to add/remove it as a descendant transaction. */
|
||||
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors);
|
||||
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
/** Set ancestor state for an entry */
|
||||
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors);
|
||||
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
/** For each transaction being removed, update ancestors and any direct children.
|
||||
* If updateDescendants is true, then also update in-mempool descendants'
|
||||
* ancestor state. */
|
||||
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants);
|
||||
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
/** Sever link between specified transaction and direct children. */
|
||||
void UpdateChildrenForRemoval(txiter entry);
|
||||
void UpdateChildrenForRemoval(txiter entry) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
/** Before calling removeUnchecked for a given transaction,
|
||||
* UpdateForRemoveFromMempool must be called on the entire (dependent) set
|
||||
@ -722,7 +722,7 @@ private:
|
||||
* transactions in a chain before we've updated all the state for the
|
||||
* removal.
|
||||
*/
|
||||
void removeUnchecked(txiter entry, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
|
||||
void removeUnchecked(txiter entry, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2866,8 +2866,9 @@ bool CChainState::ActivateBestChainStep(CValidationState& state, const CChainPar
|
||||
if (!ConnectTip(state, chainparams, pindexConnect, pindexConnect == pindexMostWork ? pblock : std::shared_ptr<const CBlock>(), connectTrace, disconnectpool)) {
|
||||
if (state.IsInvalid()) {
|
||||
// The block violates a consensus rule.
|
||||
if (!state.CorruptionPossible())
|
||||
InvalidChainFound(vpindexToConnect.back());
|
||||
if (!state.CorruptionPossible()) {
|
||||
InvalidChainFound(vpindexToConnect.front());
|
||||
}
|
||||
state = CValidationState();
|
||||
fInvalidFound = true;
|
||||
fContinue = false;
|
||||
|
@ -54,7 +54,7 @@ void CheckUniqueFileid(const BerkeleyEnvironment& env, const std::string& filena
|
||||
}
|
||||
|
||||
CCriticalSection cs_db;
|
||||
std::map<std::string, BerkeleyEnvironment> g_dbenvs; //!< Map from directory name to open db environment.
|
||||
std::map<std::string, BerkeleyEnvironment> g_dbenvs GUARDED_BY(cs_db); //!< Map from directory name to open db environment.
|
||||
} // namespace
|
||||
|
||||
BerkeleyEnvironment* GetWalletEnv(const fs::path& wallet_path, std::string& database_filename)
|
||||
@ -103,7 +103,7 @@ void BerkeleyEnvironment::Close()
|
||||
|
||||
int ret = dbenv->close(0);
|
||||
if (ret != 0)
|
||||
LogPrintf("BerkeleyEnvironment::EnvShutdown: Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret));
|
||||
LogPrintf("BerkeleyEnvironment::Close: Error %d closing database environment: %s\n", ret, DbEnv::strerror(ret));
|
||||
if (!fMockDb)
|
||||
DbEnv((u_int32_t)0).remove(strPath.c_str(), 0);
|
||||
}
|
||||
@ -169,8 +169,12 @@ bool BerkeleyEnvironment::Open(bool retry)
|
||||
nEnvFlags,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (ret != 0) {
|
||||
dbenv->close(0);
|
||||
LogPrintf("BerkeleyEnvironment::Open: Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret));
|
||||
int ret2 = dbenv->close(0);
|
||||
if (ret2 != 0) {
|
||||
LogPrintf("BerkeleyEnvironment::Open: Error %d closing failed database environment: %s\n", ret2, DbEnv::strerror(ret2));
|
||||
}
|
||||
Reset();
|
||||
if (retry) {
|
||||
// try moving the database env out of the way
|
||||
fs::path pathDatabaseBak = pathIn / strprintf("database.%d.bak", GetTime());
|
||||
|
@ -185,7 +185,7 @@ UniValue abortrescan(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
void ImportAddress(CWallet*, const CTxDestination& dest, const std::string& strLabel);
|
||||
void ImportScript(CWallet * const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript)
|
||||
void ImportScript(CWallet * const pwallet, const CScript& script, const std::string& strLabel, bool isRedeemScript) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
|
||||
{
|
||||
if (!isRedeemScript && ::IsMine(*pwallet, script) == ISMINE_SPENDABLE) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "The wallet already contains the private key for this address or script");
|
||||
@ -210,7 +210,7 @@ void ImportScript(CWallet * const pwallet, const CScript& script, const std::str
|
||||
}
|
||||
}
|
||||
|
||||
void ImportAddress(CWallet * const pwallet, const CTxDestination& dest, const std::string& strLabel)
|
||||
void ImportAddress(CWallet * const pwallet, const CTxDestination& dest, const std::string& strLabel) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
|
||||
{
|
||||
CScript script = GetScriptForDestination(dest);
|
||||
ImportScript(pwallet, script, strLabel, false);
|
||||
@ -980,7 +980,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
|
||||
UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp)
|
||||
UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int64_t timestamp) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
|
||||
{
|
||||
try {
|
||||
bool success = false;
|
||||
|
@ -726,7 +726,9 @@ void CWallet::SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator> ran
|
||||
}
|
||||
}
|
||||
|
||||
assert(copyFrom);
|
||||
if (!copyFrom) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Now copy data from copyFrom to rest:
|
||||
for (TxSpends::iterator it = range.first; it != range.second; ++it)
|
||||
@ -4822,7 +4824,7 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts) const
|
||||
}
|
||||
}
|
||||
|
||||
void CWallet::ListProTxCoins(std::vector<COutPoint>& vOutpts)
|
||||
void CWallet::ListProTxCoins(std::vector<COutPoint>& vOutpts) const
|
||||
{
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
|
||||
|
@ -751,10 +751,10 @@ private:
|
||||
|
||||
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected.
|
||||
* Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */
|
||||
void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0);
|
||||
void SyncTransaction(const CTransactionRef& tx, const CBlockIndex *pindex = nullptr, int posInBlock = 0) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/* HD derive new child key (on internal or external chain) */
|
||||
void DeriveNewChildKey(WalletBatch &batch, const CKeyMetadata& metadata, CKey& secretRet, uint32_t nAccountIndex, bool fInternal /*= false*/);
|
||||
void DeriveNewChildKey(WalletBatch &batch, const CKeyMetadata& metadata, CKey& secretRet, uint32_t nAccountIndex, bool fInternal /*= false*/) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
std::set<int64_t> setInternalKeyPool;
|
||||
std::set<int64_t> setExternalKeyPool;
|
||||
@ -772,7 +772,7 @@ private:
|
||||
* of the other AddWatchOnly which accepts a timestamp and sets
|
||||
* nTimeFirstKey more intelligently for more efficient rescans.
|
||||
*/
|
||||
bool AddWatchOnly(const CScript& dest) override;
|
||||
bool AddWatchOnly(const CScript& dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/**
|
||||
* Wallet filename from wallet=<path> command line or config option.
|
||||
@ -789,7 +789,7 @@ private:
|
||||
uint256 hashPrevBestCoinbase;
|
||||
|
||||
// A helper function which loops through wallet UTXOs
|
||||
std::unordered_set<const CWalletTx*, WalletTxHasher> GetSpendableTXs() const;
|
||||
std::unordered_set<const CWalletTx*, WalletTxHasher> GetSpendableTXs() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/**
|
||||
* The following is used to keep track of how far behind the wallet is
|
||||
@ -822,7 +822,7 @@ public:
|
||||
*/
|
||||
const std::string& GetName() const { return m_name; }
|
||||
|
||||
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool);
|
||||
void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
// Map from Key ID to key metadata.
|
||||
std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
|
||||
@ -867,12 +867,12 @@ public:
|
||||
const CWalletTx* GetWalletTx(const uint256& hash) const;
|
||||
|
||||
//! check whether we are allowed to upgrade (or already support) to the named feature
|
||||
bool CanSupportFeature(enum WalletFeature wf) const { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
|
||||
bool CanSupportFeature(enum WalletFeature wf) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
|
||||
|
||||
/**
|
||||
* populate vCoins with vector of available COutputs.
|
||||
*/
|
||||
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const;
|
||||
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe=true, const CCoinControl *coinControl = nullptr, const CAmount& nMinimumAmount = 1, const CAmount& nMaximumAmount = MAX_MONEY, const CAmount& nMinimumSumAmount = MAX_MONEY, const uint64_t nMaximumCount = 0, const int nMinDepth = 0, const int nMaxDepth = 9999999) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/**
|
||||
* Return list of available coins and locked coins grouped by non-change output address.
|
||||
@ -916,12 +916,12 @@ public:
|
||||
|
||||
bool IsSpent(const uint256& hash, unsigned int n) const;
|
||||
|
||||
bool IsLockedCoin(uint256 hash, unsigned int n) const;
|
||||
void LockCoin(const COutPoint& output);
|
||||
void UnlockCoin(const COutPoint& output);
|
||||
void UnlockAllCoins();
|
||||
void ListLockedCoins(std::vector<COutPoint>& vOutpts) const;
|
||||
void ListProTxCoins(std::vector<COutPoint>& vOutpts);
|
||||
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void LockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void UnlockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void ListLockedCoins(std::vector<COutPoint>& vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void ListProTxCoins(std::vector<COutPoint>& vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/*
|
||||
* Rescan abort properties
|
||||
@ -934,7 +934,7 @@ public:
|
||||
* keystore implementation
|
||||
* Generate a new key
|
||||
*/
|
||||
CPubKey GenerateNewKey(WalletBatch& batch, uint32_t nAccountIndex, bool fInternal /*= false*/);
|
||||
CPubKey GenerateNewKey(WalletBatch& batch, uint32_t nAccountIndex, bool fInternal /*= false*/) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
//! HaveKey implementation that also checks the mapHdPubKeys
|
||||
bool HaveKey(const CKeyID &address) const override;
|
||||
//! GetPubKey implementation that also checks the mapHdPubKeys
|
||||
@ -944,18 +944,18 @@ public:
|
||||
//! Adds a HDPubKey into the wallet(database)
|
||||
bool AddHDPubKey(WalletBatch &batch, const CExtPubKey &extPubKey, bool fInternal);
|
||||
//! loads a HDPubKey into the wallets memory
|
||||
bool LoadHDPubKey(const CHDPubKey &hdPubKey);
|
||||
bool LoadHDPubKey(const CHDPubKey &hdPubKey) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
//! Adds a key to the store, and saves it to disk.
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override;
|
||||
bool AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& key, const CPubKey &pubkey);
|
||||
bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& key, const CPubKey &pubkey) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
//! Adds a key to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
|
||||
//! Load metadata (used by LoadWallet)
|
||||
bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata);
|
||||
bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata);
|
||||
bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
|
||||
void UpdateTimeFirstKey(int64_t nCreateTime);
|
||||
bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
|
||||
void UpdateTimeFirstKey(int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
//! Adds an encrypted key to the store, and saves it to disk.
|
||||
bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) override;
|
||||
@ -976,9 +976,9 @@ public:
|
||||
std::vector<std::string> GetDestValues(const std::string& prefix) const;
|
||||
|
||||
//! Adds a watch-only address to the store, and saves it to disk.
|
||||
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime);
|
||||
bool AddWatchOnly(const CScript& dest, int64_t nCreateTime) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
bool RemoveWatchOnly(const CScript &dest) override;
|
||||
bool RemoveWatchOnly(const CScript &dest) override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
//! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
|
||||
bool LoadWatchOnly(const CScript &dest);
|
||||
|
||||
@ -989,16 +989,16 @@ public:
|
||||
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
|
||||
bool EncryptWallet(const SecureString& strWalletPassphrase);
|
||||
|
||||
void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const;
|
||||
void GetKeyBirthTimes(std::map<CTxDestination, int64_t> &mapKeyBirth) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
unsigned int ComputeTimeSmart(const CWalletTx& wtx) const;
|
||||
|
||||
/**
|
||||
* Increment the next transaction order id
|
||||
* @return next transaction order id
|
||||
*/
|
||||
int64_t IncOrderPosNext(WalletBatch *batch = nullptr);
|
||||
int64_t IncOrderPosNext(WalletBatch *batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
DBErrors ReorderTransactions();
|
||||
bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "");
|
||||
bool AccountMove(std::string strFrom, std::string strTo, CAmount nAmount, std::string strComment = "") EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool GetAccountDestination(CTxDestination &dest, std::string strAccount, bool bForceNew = false);
|
||||
|
||||
void MarkDirty();
|
||||
@ -1007,7 +1007,7 @@ public:
|
||||
void TransactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime) override;
|
||||
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
|
||||
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexDisconnected) override;
|
||||
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate);
|
||||
bool AddToWalletIfInvolvingMe(const CTransactionRef& tx, const CBlockIndex* pIndex, int posInBlock, bool fUpdate) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
int64_t RescanFromTime(int64_t startTime, const WalletRescanReserver& reserver, bool update);
|
||||
CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, const WalletRescanReserver& reserver, bool fUpdate = false);
|
||||
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
|
||||
@ -1037,7 +1037,7 @@ public:
|
||||
* calling CreateTransaction();
|
||||
*/
|
||||
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
|
||||
bool SignTransaction(CMutableTransaction& tx);
|
||||
bool SignTransaction(CMutableTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
/**
|
||||
* Create a new transaction paying the recipients with a set of coins
|
||||
@ -1059,8 +1059,8 @@ public:
|
||||
static CFeeRate m_discard_rate;
|
||||
|
||||
bool NewKeyPool();
|
||||
size_t KeypoolCountExternalKeys();
|
||||
size_t KeypoolCountInternalKeys();
|
||||
size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
size_t KeypoolCountInternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
bool TopUpKeyPool(unsigned int kpSize = 0);
|
||||
void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fInternal);
|
||||
void KeepKey(int64_t nIndex);
|
||||
@ -1070,10 +1070,10 @@ public:
|
||||
/**
|
||||
* Marks all keys in the keypool up to and including reserve_key as used.
|
||||
*/
|
||||
void MarkReserveKeysAsUsed(int64_t keypool_id);
|
||||
void MarkReserveKeysAsUsed(int64_t keypool_id) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
const std::map<CKeyID, int64_t>& GetAllReserveKeys() const { return m_pool_key_to_index; }
|
||||
|
||||
std::set< std::set<CTxDestination> > GetAddressGroupings();
|
||||
std::set<std::set<CTxDestination>> GetAddressGroupings() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
std::map<CTxDestination, CAmount> GetAddressBalances();
|
||||
|
||||
std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
|
||||
@ -1101,7 +1101,7 @@ public:
|
||||
DBErrors LoadWallet(bool& fFirstRunRet);
|
||||
void AutoLockMasternodeCollaterals();
|
||||
DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
|
||||
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
|
||||
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
|
||||
|
||||
@ -1121,7 +1121,7 @@ public:
|
||||
|
||||
void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
|
||||
|
||||
unsigned int GetKeyPoolSize()
|
||||
unsigned int GetKeyPoolSize() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet)
|
||||
{
|
||||
AssertLockHeld(cs_wallet); // set{Ex,In}ternalKeyPool
|
||||
return setInternalKeyPool.size() + setExternalKeyPool.size();
|
||||
@ -1137,7 +1137,7 @@ public:
|
||||
int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
|
||||
|
||||
//! Get wallet transactions that conflict with given transaction (spend same outputs)
|
||||
std::set<uint256> GetConflicts(const uint256& txid) const;
|
||||
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
//! Flush wallet (bitdb flush)
|
||||
void Flush(bool shutdown=false);
|
||||
@ -1228,7 +1228,7 @@ public:
|
||||
* Obviously holding cs_main/cs_wallet when going into this call may cause
|
||||
* deadlock
|
||||
*/
|
||||
void BlockUntilSyncedToCurrentChain();
|
||||
void BlockUntilSyncedToCurrentChain() LOCKS_EXCLUDED(cs_wallet);
|
||||
};
|
||||
|
||||
/** A key allocated from the key pool. */
|
||||
|
@ -245,7 +245,7 @@ public:
|
||||
|
||||
bool
|
||||
ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
CWalletScanState &wss, std::string& strType, std::string& strErr)
|
||||
CWalletScanState &wss, std::string& strType, std::string& strErr) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
|
||||
{
|
||||
try {
|
||||
// Unserialize
|
||||
|
@ -10,9 +10,9 @@
|
||||
#include <hash.h>
|
||||
|
||||
CCriticalSection cs_warnings;
|
||||
std::string strMiscWarning;
|
||||
bool fLargeWorkForkFound = false;
|
||||
bool fLargeWorkInvalidChainFound = false;
|
||||
std::string strMiscWarning GUARDED_BY(cs_warnings);
|
||||
bool fLargeWorkForkFound GUARDED_BY(cs_warnings) = false;
|
||||
bool fLargeWorkInvalidChainFound GUARDED_BY(cs_warnings) = false;
|
||||
|
||||
void SetMiscWarning(const std::string& strWarning)
|
||||
{
|
||||
|
@ -4,8 +4,18 @@
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test the fundrawtransaction RPC."""
|
||||
|
||||
from decimal import Decimal
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import *
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
assert_fee_amount,
|
||||
assert_greater_than,
|
||||
assert_greater_than_or_equal,
|
||||
assert_raises_rpc_error,
|
||||
connect_nodes_bi,
|
||||
count_bytes,
|
||||
find_vout_for_address,
|
||||
)
|
||||
|
||||
|
||||
def get_unspent(listunspent, amount):
|
||||
@ -58,6 +68,11 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
watchonly_amount = Decimal(2000)
|
||||
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
|
||||
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
|
||||
|
||||
# Lock UTXO so nodes[0] doesn't accidentally spend it
|
||||
watchonly_vout = find_vout_for_address(self.nodes[0], watchonly_txid, watchonly_address)
|
||||
self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
|
||||
|
||||
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
|
||||
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 15)
|
||||
@ -463,6 +478,9 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
connect_nodes_bi(self.nodes,0,3)
|
||||
# Again lock the watchonly UTXO or nodes[0] may spend it, because
|
||||
# lockunspent is memory-only and thus lost on restart
|
||||
self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
|
||||
self.sync_all()
|
||||
|
||||
# drain the keypool
|
||||
|
@ -628,3 +628,14 @@ def mine_large_block(node, utxos=None):
|
||||
fee = 100 * node.getnetworkinfo()["relayfee"]
|
||||
create_lots_of_big_transactions(node, txouts, utxos, num, fee=fee)
|
||||
node.generate(1)
|
||||
|
||||
def find_vout_for_address(node, txid, addr):
|
||||
"""
|
||||
Locate the vout index of the given transaction sending to the
|
||||
given address. Raises runtime error exception if not found.
|
||||
"""
|
||||
tx = node.getrawtransaction(txid, True)
|
||||
for i in range(len(tx["vout"])):
|
||||
if any([addr == a for a in tx["vout"][i]["scriptPubKey"]["addresses"]]):
|
||||
return i
|
||||
raise RuntimeError("Vout not found for address: txid=%s, addr=%s" % (txid, addr))
|
||||
|
Loading…
Reference in New Issue
Block a user