mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
Merge #9381: Remove CWalletTx merging logic from AddToWallet
28b112e9bd3fd1181c0720306051ba7efca8b436 Get rid of BindWallet (Russell Yanofsky) d002f9d15d938e78360ad906f2d74a249c7e923e Disable CWalletTx copy constructor (Russell Yanofsky) 65b9d8f8ddb5a838454efc8bdd6576f0deb65f6d Avoid copying CWalletTx in LoadToWallet (Russell Yanofsky) bd2fbc7cdbec46400341209f4cb7e69e5b2cee19 Get rid of unneeded CWalletTx::Init parameter (Russell Yanofsky) 2b9cba206594bfbcefcef0c88a0bf793819643bd Remove CWalletTx merging logic from AddToWallet (Russell Yanofsky) Pull request description: This is a pure refactoring, no behavior is changing. Instead of AddToWallet taking a temporary CWalletTx object and then potentially merging it with a pre-existing CWalletTx, have it take a callback so callers can update the pre-existing CWalletTx directly. This makes AddToWallet simpler because now it is only has to be concerned with saving CWalletTx objects and not merging them. This makes AddToWallet calls clearer because they can now make direct updates to CWalletTx entries without having to make temporary objects and then worry about how they will be merged. Motivation for this change came from the bumpfee PR #8456 where we wanted to be able to call AddToWallet to make a simple update to an existing transaction, but were reluctant to, because the existing CWalletTx merging logic did not apply and seemed dangerous try to update as part of that PR. After this refactoring, the bumpfee PR could call AddToWallet safely instead of implementing a duplicate AddToWallet function. This also allows getting rid of the CWalletTx copy constructor to prevent unintentional copying. ACKs for top commit: MarcoFalke: Anyway, re-ACK 28b112e9bd3fd1181c0720306051ba7efca8b436 Tree-SHA512: 528dd088714472a237500b200f4433db850bdb7fc29c5e5d81cae48072061dfb967f7c37edd90b33f24901239f9be982988547c1f8c80abc25fb243fbf7330ef
This commit is contained in:
parent
849b5ed2a4
commit
d11a933c5b
@ -302,7 +302,6 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed. Make sure the tx has at least one input.");
|
||||
}
|
||||
uint256 hashTx = tx.GetHash();
|
||||
CWalletTx wtx(pwallet, MakeTransactionRef(std::move(tx)));
|
||||
|
||||
CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CMerkleBlock merkleBlock;
|
||||
@ -329,10 +328,10 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
|
||||
unsigned int txnIndex = vIndex[it - vMatch.begin()];
|
||||
|
||||
CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, height, merkleBlock.header.GetHash(), txnIndex);
|
||||
wtx.m_confirm = confirm;
|
||||
|
||||
if (pwallet->IsMine(*wtx.tx)) {
|
||||
pwallet->AddToWallet(wtx, false);
|
||||
CTransactionRef tx_ref = MakeTransactionRef(tx);
|
||||
if (pwallet->IsMine(*tx_ref)) {
|
||||
pwallet->AddToWallet(std::move(tx_ref), confirm);
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
|
@ -1628,7 +1628,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
|
||||
UniValue transactions(UniValue::VARR);
|
||||
|
||||
for (const std::pair<const uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
|
||||
CWalletTx tx = pairWtx.second;
|
||||
const CWalletTx& tx = pairWtx.second;
|
||||
|
||||
if (depth == -1 || abs(tx.GetDepthInMainChain()) < depth) {
|
||||
ListTransactions(pwallet, tx, 0, true, transactions, filter, nullptr /* filter_label */);
|
||||
|
@ -25,8 +25,6 @@ BOOST_FIXTURE_TEST_SUITE(coinselector_tests, WalletTestingSetup)
|
||||
// we repeat those tests this many times and only complain if all iterations of the test fail
|
||||
#define RANDOM_REPEATS 5
|
||||
|
||||
std::vector<std::unique_ptr<CWalletTx>> wtxn;
|
||||
|
||||
typedef std::set<CInputCoin> CoinSet;
|
||||
|
||||
static std::vector<COutput> vCoins;
|
||||
@ -76,16 +74,14 @@ static void add_coin(CWallet& wallet, const CAmount& nValue, int nAge = 6*24, bo
|
||||
// so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
|
||||
tx.vin.resize(1);
|
||||
}
|
||||
std::unique_ptr<CWalletTx> wtx = std::make_unique<CWalletTx>(&wallet, MakeTransactionRef(std::move(tx)));
|
||||
CWalletTx* wtx = wallet.AddToWallet(MakeTransactionRef(std::move(tx)), /* confirm= */ {});
|
||||
if (fIsFromMe)
|
||||
{
|
||||
wtx->m_amounts[CWalletTx::DEBIT].Set(ISMINE_SPENDABLE, 1);
|
||||
wtx->m_is_cache_empty = false;
|
||||
}
|
||||
COutput output(wtx.get(), nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
|
||||
COutput output(wtx, nInput, nAge, true /* spendable */, true /* solvable */, true /* safe */);
|
||||
vCoins.push_back(output);
|
||||
wallet.AddToWallet(*wtx.get());
|
||||
wtxn.emplace_back(std::move(wtx));
|
||||
}
|
||||
static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0, bool spendable = false)
|
||||
{
|
||||
@ -95,7 +91,6 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa
|
||||
static void empty_wallet(void)
|
||||
{
|
||||
vCoins.clear();
|
||||
wtxn.clear();
|
||||
balance = 0;
|
||||
}
|
||||
|
||||
|
@ -23,14 +23,12 @@ BOOST_AUTO_TEST_CASE(psbt_updater_test)
|
||||
CDataStream s_prev_tx1(ParseHex("0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7501000000171600145f275f436b09a8cc9a2eb2a2f528485c68a56323feffffff02d8231f1b0100000017a914aed962d6654f9a2b36608eb9d64d2b260db4f1118700c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88702483045022100a22edcc6e5bc511af4cc4ae0de0fcd75c7e04d8c1c3a8aa9d820ed4b967384ec02200642963597b9b1bc22c75e9f3e117284a962188bf5e8a74c895089046a20ad770121035509a48eb623e10aace8bfd0212fdb8a8e5af3c94b0b133b95e114cab89e4f7965000000"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransactionRef prev_tx1;
|
||||
s_prev_tx1 >> prev_tx1;
|
||||
CWalletTx prev_wtx1(&m_wallet, prev_tx1);
|
||||
m_wallet.mapWallet.emplace(prev_wtx1.GetHash(), std::move(prev_wtx1));
|
||||
m_wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(prev_tx1->GetHash()), std::forward_as_tuple(&m_wallet, prev_tx1));
|
||||
|
||||
CDataStream s_prev_tx2(ParseHex("0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransactionRef prev_tx2;
|
||||
s_prev_tx2 >> prev_tx2;
|
||||
CWalletTx prev_wtx2(&m_wallet, prev_tx2);
|
||||
m_wallet.mapWallet.emplace(prev_wtx2.GetHash(), std::move(prev_wtx2));
|
||||
m_wallet.mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(prev_tx2->GetHash()), std::forward_as_tuple(&m_wallet, prev_tx2));
|
||||
|
||||
// Add scripts
|
||||
CScript rs1;
|
||||
|
@ -419,6 +419,7 @@ BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
|
||||
static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lockTime, int64_t mockTime, int64_t blockTime)
|
||||
{
|
||||
CMutableTransaction tx;
|
||||
CWalletTx::Confirmation confirm;
|
||||
tx.nLockTime = lockTime;
|
||||
SetMockTime(mockTime);
|
||||
CBlockIndex* block = nullptr;
|
||||
@ -430,23 +431,15 @@ static int64_t AddTx(ChainstateManager& chainman, CWallet& wallet, uint32_t lock
|
||||
block = inserted.first->second;
|
||||
block->nTime = blockTime;
|
||||
block->phashBlock = &hash;
|
||||
confirm = {CWalletTx::Status::CONFIRMED, block->nHeight, hash, 0};
|
||||
}
|
||||
|
||||
CWalletTx wtx(&wallet, MakeTransactionRef(tx));
|
||||
LOCK(wallet.cs_wallet);
|
||||
// If transaction is already in map, to avoid inconsistencies, unconfirmation
|
||||
// is needed before confirm again with different block.
|
||||
std::map<uint256, CWalletTx>::iterator it = wallet.mapWallet.find(wtx.GetHash());
|
||||
if (it != wallet.mapWallet.end()) {
|
||||
return wallet.AddToWallet(MakeTransactionRef(tx), confirm, [&](CWalletTx& wtx, bool /* new_tx */) {
|
||||
wtx.setUnconfirmed();
|
||||
wallet.AddToWallet(wtx);
|
||||
}
|
||||
if (block) {
|
||||
CWalletTx::Confirmation confirm(CWalletTx::Status::CONFIRMED, block->nHeight, block->GetBlockHash(), 0);
|
||||
wtx.m_confirm = confirm;
|
||||
}
|
||||
wallet.AddToWallet(wtx);
|
||||
return wallet.mapWallet.at(wtx.GetHash()).nTimeSmart;
|
||||
return true;
|
||||
})->nTimeSmart;
|
||||
}
|
||||
|
||||
// Simple test to verify assignment of CWalletTx::nSmartTime value. Could be
|
||||
|
@ -848,19 +848,19 @@ bool CWallet::IsSpentKey(const uint256& hash, unsigned int n) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx, bool fFlushOnClose)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
|
||||
WalletBatch batch(GetDatabase(), fFlushOnClose);
|
||||
|
||||
uint256 hash = wtxIn.GetHash();
|
||||
uint256 hash = tx->GetHash();
|
||||
|
||||
if (IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE)) {
|
||||
// Mark used destinations
|
||||
std::set<CTxDestination> tx_destinations;
|
||||
|
||||
for (const CTxIn& txin : wtxIn.tx->vin) {
|
||||
for (const CTxIn& txin : tx->vin) {
|
||||
const COutPoint& op = txin.prevout;
|
||||
SetSpentKeyState(batch, op.hash, op.n, true, tx_destinations);
|
||||
}
|
||||
@ -869,11 +869,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
}
|
||||
|
||||
// Inserts only if not already there, returns tx inserted or tx found
|
||||
std::pair<std::map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(std::make_pair(hash, wtxIn));
|
||||
auto ret = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(this, tx));
|
||||
CWalletTx& wtx = (*ret.first).second;
|
||||
wtx.BindWallet(this);
|
||||
bool fInsertedNew = ret.second;
|
||||
bool fUpdated = update_wtx && update_wtx(wtx, fInsertedNew);
|
||||
if (fInsertedNew) {
|
||||
wtx.m_confirm = confirm;
|
||||
wtx.nTimeReceived = GetTime();
|
||||
wtx.nOrderPos = IncOrderPosNext(&batch);
|
||||
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
|
||||
@ -891,24 +892,18 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
}
|
||||
}
|
||||
|
||||
bool fUpdated = false;
|
||||
if (!fInsertedNew)
|
||||
{
|
||||
if (wtxIn.m_confirm.status != wtx.m_confirm.status) {
|
||||
wtx.m_confirm.status = wtxIn.m_confirm.status;
|
||||
wtx.m_confirm.nIndex = wtxIn.m_confirm.nIndex;
|
||||
wtx.m_confirm.hashBlock = wtxIn.m_confirm.hashBlock;
|
||||
wtx.m_confirm.block_height = wtxIn.m_confirm.block_height;
|
||||
if (confirm.status != wtx.m_confirm.status) {
|
||||
wtx.m_confirm.status = confirm.status;
|
||||
wtx.m_confirm.nIndex = confirm.nIndex;
|
||||
wtx.m_confirm.hashBlock = confirm.hashBlock;
|
||||
wtx.m_confirm.block_height = confirm.block_height;
|
||||
fUpdated = true;
|
||||
} else {
|
||||
assert(wtx.m_confirm.nIndex == wtxIn.m_confirm.nIndex);
|
||||
assert(wtx.m_confirm.hashBlock == wtxIn.m_confirm.hashBlock);
|
||||
assert(wtx.m_confirm.block_height == wtxIn.m_confirm.block_height);
|
||||
}
|
||||
if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
|
||||
{
|
||||
wtx.fFromMe = wtxIn.fFromMe;
|
||||
fUpdated = true;
|
||||
assert(wtx.m_confirm.nIndex == confirm.nIndex);
|
||||
assert(wtx.m_confirm.hashBlock == confirm.hashBlock);
|
||||
assert(wtx.m_confirm.block_height == confirm.block_height);
|
||||
}
|
||||
|
||||
auto mnList = deterministicMNManager->GetListAtChainTip();
|
||||
@ -924,12 +919,12 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
}
|
||||
|
||||
//// debug print
|
||||
WalletLogPrintf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
|
||||
WalletLogPrintf("AddToWallet %s %s%s\n", hash.ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
|
||||
|
||||
// Write to disk
|
||||
if (fInsertedNew || fUpdated)
|
||||
if (!batch.WriteTx(wtx))
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
// Break debit/credit balance caches:
|
||||
wtx.MarkDirty();
|
||||
@ -943,7 +938,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
|
||||
if (!strCmd.empty())
|
||||
{
|
||||
ReplaceAll(strCmd, "%s", wtxIn.GetHash().GetHex());
|
||||
ReplaceAll(strCmd, "%s", hash.GetHex());
|
||||
#ifndef WIN32
|
||||
// Substituting the wallet name isn't currently supported on windows
|
||||
// because windows shell escaping has not been implemented yet:
|
||||
@ -960,36 +955,37 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
fAnonymizableTallyCached = false;
|
||||
fAnonymizableTallyCachedNonDenom = false;
|
||||
|
||||
return true;
|
||||
return &wtx;
|
||||
}
|
||||
|
||||
void CWallet::LoadToWallet(CWalletTx& wtxIn)
|
||||
bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx)
|
||||
{
|
||||
const auto& ins = mapWallet.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(this, nullptr));
|
||||
CWalletTx& wtx = ins.first->second;
|
||||
if (!fill_wtx(wtx, ins.second)) {
|
||||
return false;
|
||||
}
|
||||
// If wallet doesn't have a chain (e.g dash-wallet), don't bother to update txn.
|
||||
if (HaveChain()) {
|
||||
bool active;
|
||||
int height;
|
||||
if (chain().findBlock(wtxIn.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
|
||||
if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
|
||||
// Update cached block height variable since it not stored in the
|
||||
// serialized transaction.
|
||||
wtxIn.m_confirm.block_height = height;
|
||||
} else if (wtxIn.isConflicted() || wtxIn.isConfirmed()) {
|
||||
wtx.m_confirm.block_height = height;
|
||||
} else if (wtx.isConflicted() || wtx.isConfirmed()) {
|
||||
// If tx block (or conflicting block) was reorged out of chain
|
||||
// while the wallet was shutdown, change tx status to UNCONFIRMED
|
||||
// and reset block height, hash, and index. ABANDONED tx don't have
|
||||
// associated blocks and don't need to be updated. The case where a
|
||||
// transaction was reorged out while online and then reconfirmed
|
||||
// while offline is covered by the rescan logic.
|
||||
wtxIn.setUnconfirmed();
|
||||
wtxIn.m_confirm.hashBlock = uint256();
|
||||
wtxIn.m_confirm.block_height = 0;
|
||||
wtxIn.m_confirm.nIndex = 0;
|
||||
wtx.setUnconfirmed();
|
||||
wtx.m_confirm.hashBlock = uint256();
|
||||
wtx.m_confirm.block_height = 0;
|
||||
wtx.m_confirm.nIndex = 0;
|
||||
}
|
||||
}
|
||||
uint256 hash = wtxIn.GetHash();
|
||||
const auto& ins = mapWallet.emplace(hash, wtxIn);
|
||||
CWalletTx& wtx = ins.first->second;
|
||||
wtx.BindWallet(this);
|
||||
if (/* insertion took place */ ins.second) {
|
||||
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
|
||||
}
|
||||
@ -1003,6 +999,7 @@ void CWallet::LoadToWallet(CWalletTx& wtxIn)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Confirmation confirm, WalletBatch& batch, bool fUpdate)
|
||||
@ -1048,13 +1045,9 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef& ptx, CWalletTx::Co
|
||||
}
|
||||
}
|
||||
|
||||
CWalletTx wtx(this, ptx);
|
||||
|
||||
// Block disconnection override an abandoned tx as unconfirmed
|
||||
// which means user may have to call abandontransaction again
|
||||
wtx.m_confirm = confirm;
|
||||
|
||||
return AddToWallet(wtx, false);
|
||||
return AddToWallet(MakeTransactionRef(tx), confirm, /* update_wtx= */ nullptr, /* fFlushOnClose= */ false);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -3771,32 +3764,34 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
|
||||
void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
WalletLogPrintf("CommitTransaction:\n%s", tx->ToString()); /* Continued */
|
||||
|
||||
CWalletTx wtxNew(this, std::move(tx));
|
||||
wtxNew.mapValue = std::move(mapValue);
|
||||
wtxNew.vOrderForm = std::move(orderForm);
|
||||
wtxNew.fTimeReceivedIsTxTime = true;
|
||||
wtxNew.fFromMe = true;
|
||||
|
||||
WalletLogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); /* Continued */
|
||||
// Add tx to wallet, because if it has change it's also ours,
|
||||
// otherwise just for transaction history.
|
||||
AddToWallet(wtxNew);
|
||||
AddToWallet(tx, {}, [&](CWalletTx& wtx, bool new_tx) {
|
||||
CHECK_NONFATAL(wtx.mapValue.empty());
|
||||
CHECK_NONFATAL(wtx.vOrderForm.empty());
|
||||
wtx.mapValue = std::move(mapValue);
|
||||
wtx.vOrderForm = std::move(orderForm);
|
||||
wtx.fTimeReceivedIsTxTime = true;
|
||||
wtx.fFromMe = true;
|
||||
return true;
|
||||
});
|
||||
|
||||
// Notify that old coins are spent
|
||||
std::set<uint256> updated_hahes;
|
||||
for (const CTxIn& txin : wtxNew.tx->vin){
|
||||
for (const CTxIn& txin : tx->vin){
|
||||
// notify only once
|
||||
if(updated_hahes.find(txin.prevout.hash) != updated_hahes.end()) continue;
|
||||
|
||||
CWalletTx &coin = mapWallet.at(txin.prevout.hash);
|
||||
coin.BindWallet(this);
|
||||
coin.MarkDirty();
|
||||
NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
|
||||
updated_hahes.insert(txin.prevout.hash);
|
||||
}
|
||||
// Get the inserted-CWalletTx from mapWallet so that the
|
||||
// fInMempool flag is cached properly
|
||||
CWalletTx& wtx = mapWallet.at(wtxNew.GetHash());
|
||||
CWalletTx& wtx = mapWallet.at(tx->GetHash());
|
||||
|
||||
if (!fBroadcastTransactions) {
|
||||
// Don't submit tx to the mempool
|
||||
@ -3904,7 +3899,6 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
|
||||
MarkDirty();
|
||||
|
||||
WalletLogPrintf("ZapSelectTx completed for %d transactions.\n", vHashOut.size());
|
||||
|
||||
return DBErrors::LOAD_OK;
|
||||
}
|
||||
|
||||
|
@ -355,15 +355,15 @@ public:
|
||||
mutable bool fInMempool;
|
||||
mutable CAmount nChangeCached;
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn, CTransactionRef arg)
|
||||
: tx(std::move(arg))
|
||||
CWalletTx(const CWallet* wallet, CTransactionRef arg)
|
||||
: pwallet(wallet),
|
||||
tx(std::move(arg))
|
||||
{
|
||||
Init(pwalletIn);
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init(const CWallet* pwalletIn)
|
||||
void Init()
|
||||
{
|
||||
pwallet = pwalletIn;
|
||||
mapValue.clear();
|
||||
vOrderForm.clear();
|
||||
fTimeReceivedIsTxTime = false;
|
||||
@ -431,7 +431,7 @@ public:
|
||||
template<typename Stream>
|
||||
void Unserialize(Stream& s)
|
||||
{
|
||||
Init(nullptr);
|
||||
Init();
|
||||
|
||||
std::vector<uint256> dummy_vector1; //!< Used to be vMerkleBranch
|
||||
std::vector<CMerkleTx> dummy_vector2; //!< Used to be vtxPrev
|
||||
@ -483,12 +483,6 @@ public:
|
||||
m_is_cache_empty = true;
|
||||
}
|
||||
|
||||
void BindWallet(CWallet *pwalletIn)
|
||||
{
|
||||
pwallet = pwalletIn;
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
const CWallet* GetWallet() const
|
||||
{
|
||||
return pwallet;
|
||||
@ -585,6 +579,12 @@ public:
|
||||
const uint256& GetHash() const { return tx->GetHash(); }
|
||||
bool IsCoinBase() const { return tx->IsCoinBase(); }
|
||||
bool IsImmatureCoinBase() const;
|
||||
|
||||
// Disable copying of CWalletTx objects to prevent bugs where instances get
|
||||
// copied in and out of the mapWallet map, and fields are updated in the
|
||||
// wrong copy.
|
||||
CWalletTx(CWalletTx const &) = delete;
|
||||
void operator=(CWalletTx const &x) = delete;
|
||||
};
|
||||
|
||||
struct WalletTxHasher
|
||||
@ -984,8 +984,17 @@ public:
|
||||
DBErrors ReorderTransactions();
|
||||
|
||||
void MarkDirty();
|
||||
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
|
||||
void LoadToWallet(CWalletTx& wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
|
||||
//! Callback for updating transaction metadata in mapWallet.
|
||||
//!
|
||||
//! @param wtx - reference to mapWallet transaction to update
|
||||
//! @param new_tx - true if wtx is newly inserted, false if it previously existed
|
||||
//!
|
||||
//! @return true if wtx is changed and needs to be saved to disk, otherwise false
|
||||
using UpdateWalletTxFn = std::function<bool(CWalletTx& wtx, bool new_tx)>;
|
||||
|
||||
CWalletTx* AddToWallet(CTransactionRef tx, const CWalletTx::Confirmation& confirm, const UpdateWalletTxFn& update_wtx=nullptr, bool fFlushOnClose=true);
|
||||
bool LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||
void transactionAddedToMempool(const CTransactionRef& tx, int64_t nAcceptTime) override;
|
||||
void blockConnected(const CBlock& block, int height) override;
|
||||
void blockDisconnected(const CBlock& block, int height) override;
|
||||
|
@ -264,36 +264,43 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
|
||||
} else if (strType == DBKeys::TX) {
|
||||
uint256 hash;
|
||||
ssKey >> hash;
|
||||
CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
|
||||
ssValue >> wtx;
|
||||
if (wtx.GetHash() != hash)
|
||||
// LoadToWallet call below creates a new CWalletTx that fill_wtx
|
||||
// callback fills with transaction metadata.
|
||||
auto fill_wtx = [&](CWalletTx& wtx, bool new_tx) {
|
||||
assert(new_tx);
|
||||
ssValue >> wtx;
|
||||
if (wtx.GetHash() != hash)
|
||||
return false;
|
||||
|
||||
// Undo serialize changes in 31600
|
||||
if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
|
||||
{
|
||||
if (!ssValue.empty())
|
||||
{
|
||||
char fTmp;
|
||||
char fUnused;
|
||||
std::string unused_string;
|
||||
ssValue >> fTmp >> fUnused >> unused_string;
|
||||
strErr = strprintf("LoadWallet() upgrading tx ver=%d %d %s",
|
||||
wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
|
||||
wtx.fTimeReceivedIsTxTime = fTmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
|
||||
wtx.fTimeReceivedIsTxTime = 0;
|
||||
}
|
||||
wss.vWalletUpgrade.push_back(hash);
|
||||
}
|
||||
|
||||
if (wtx.nOrderPos == -1)
|
||||
wss.fAnyUnordered = true;
|
||||
|
||||
return true;
|
||||
};
|
||||
if (!pwallet->LoadToWallet(hash, fill_wtx)) {
|
||||
return false;
|
||||
|
||||
// Undo serialize changes in 31600
|
||||
if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703)
|
||||
{
|
||||
if (!ssValue.empty())
|
||||
{
|
||||
char fTmp;
|
||||
char fUnused;
|
||||
std::string unused_string;
|
||||
ssValue >> fTmp >> fUnused >> unused_string;
|
||||
strErr = strprintf("LoadWallet() upgrading tx ver=%d %d %s",
|
||||
wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString());
|
||||
wtx.fTimeReceivedIsTxTime = fTmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
strErr = strprintf("LoadWallet() repairing tx ver=%d %s", wtx.fTimeReceivedIsTxTime, hash.ToString());
|
||||
wtx.fTimeReceivedIsTxTime = 0;
|
||||
}
|
||||
wss.vWalletUpgrade.push_back(hash);
|
||||
}
|
||||
|
||||
if (wtx.nOrderPos == -1)
|
||||
wss.fAnyUnordered = true;
|
||||
|
||||
pwallet->LoadToWallet(wtx);
|
||||
} else if (strType == DBKeys::WATCHS) {
|
||||
wss.nWatchKeys++;
|
||||
CScript script;
|
||||
@ -665,7 +672,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
|
||||
return result;
|
||||
}
|
||||
|
||||
DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx)
|
||||
DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWalletTx>& vWtx)
|
||||
{
|
||||
DBErrors result = DBErrors::LOAD_OK;
|
||||
|
||||
@ -703,12 +710,9 @@ DBErrors WalletBatch::FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CW
|
||||
if (strType == DBKeys::TX) {
|
||||
uint256 hash;
|
||||
ssKey >> hash;
|
||||
|
||||
CWalletTx wtx(nullptr /* pwallet */, MakeTransactionRef());
|
||||
ssValue >> wtx;
|
||||
|
||||
vTxHash.push_back(hash);
|
||||
vWtx.push_back(wtx);
|
||||
vWtx.emplace_back(nullptr /* wallet */, nullptr /* tx */);
|
||||
ssValue >> vWtx.back();
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
@ -723,7 +727,7 @@ DBErrors WalletBatch::ZapSelectTx(std::vector<uint256>& vTxHashIn, std::vector<u
|
||||
{
|
||||
// build list of wallet TXs and hashes
|
||||
std::vector<uint256> vTxHash;
|
||||
std::vector<CWalletTx> vWtx;
|
||||
std::list<CWalletTx> vWtx;
|
||||
DBErrors err = FindWalletTx(vTxHash, vWtx);
|
||||
if (err != DBErrors::LOAD_OK) {
|
||||
return err;
|
||||
|
@ -208,7 +208,7 @@ public:
|
||||
bool EraseDestData(const std::string &address, const std::string &key);
|
||||
|
||||
DBErrors LoadWallet(CWallet* pwallet);
|
||||
DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::vector<CWalletTx>& vWtx);
|
||||
DBErrors FindWalletTx(std::vector<uint256>& vTxHash, std::list<CWalletTx>& vWtx);
|
||||
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut);
|
||||
/* Function to determine if a certain KV/key-type is a key (cryptographical key) type */
|
||||
static bool IsKeyType(const std::string& strType);
|
||||
|
Loading…
Reference in New Issue
Block a user