Allow locked UTXOs to be store in the wallet database

This commit is contained in:
Samuel Dobson
2021-09-23 00:17:55 +12:00
parent 51c7d88e67
commit c52789365e
6 changed files with 58 additions and 18 deletions

View File

@@ -122,10 +122,10 @@ public:
virtual bool displayAddress(const CTxDestination& dest) = 0; virtual bool displayAddress(const CTxDestination& dest) = 0;
//! Lock coin. //! Lock coin.
virtual void lockCoin(const COutPoint& output) = 0; virtual bool lockCoin(const COutPoint& output) = 0;
//! Unlock coin. //! Unlock coin.
virtual void unlockCoin(const COutPoint& output) = 0; virtual bool unlockCoin(const COutPoint& output) = 0;
//! Return whether coin is locked. //! Return whether coin is locked.
virtual bool isLockedCoin(const COutPoint& output) = 0; virtual bool isLockedCoin(const COutPoint& output) = 0;

View File

@@ -214,12 +214,12 @@ public:
LOCK(m_wallet->cs_wallet); LOCK(m_wallet->cs_wallet);
return m_wallet->DisplayAddress(dest); return m_wallet->DisplayAddress(dest);
} }
void lockCoin(const COutPoint& output) override bool lockCoin(const COutPoint& output) override
{ {
LOCK(m_wallet->cs_wallet); LOCK(m_wallet->cs_wallet);
return m_wallet->LockCoin(output); return m_wallet->LockCoin(output);
} }
void unlockCoin(const COutPoint& output) override bool unlockCoin(const COutPoint& output) override
{ {
LOCK(m_wallet->cs_wallet); LOCK(m_wallet->cs_wallet);
return m_wallet->UnlockCoin(output); return m_wallet->UnlockCoin(output);

View File

@@ -589,11 +589,16 @@ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
return false; return false;
} }
void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid) void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch)
{ {
mapTxSpends.insert(std::make_pair(outpoint, wtxid)); mapTxSpends.insert(std::make_pair(outpoint, wtxid));
setLockedCoins.erase(outpoint); if (batch) {
UnlockCoin(outpoint, batch);
} else {
WalletBatch temp_batch(GetDatabase());
UnlockCoin(outpoint, &temp_batch);
}
std::pair<TxSpends::iterator, TxSpends::iterator> range; std::pair<TxSpends::iterator, TxSpends::iterator> range;
range = mapTxSpends.equal_range(outpoint); range = mapTxSpends.equal_range(outpoint);
@@ -601,7 +606,7 @@ void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
} }
void CWallet::AddToSpends(const uint256& wtxid) void CWallet::AddToSpends(const uint256& wtxid, WalletBatch* batch)
{ {
auto it = mapWallet.find(wtxid); auto it = mapWallet.find(wtxid);
assert(it != mapWallet.end()); assert(it != mapWallet.end());
@@ -610,7 +615,7 @@ void CWallet::AddToSpends(const uint256& wtxid)
return; return;
for (const CTxIn& txin : thisTx.tx->vin) for (const CTxIn& txin : thisTx.tx->vin)
AddToSpends(txin.prevout, wtxid); AddToSpends(txin.prevout, wtxid, batch);
} }
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
@@ -910,7 +915,7 @@ CWalletTx* CWallet::AddToWallet(CTransactionRef tx, const CWalletTx::Confirmatio
wtx.nOrderPos = IncOrderPosNext(&batch); wtx.nOrderPos = IncOrderPosNext(&batch);
wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx)); wtx.m_it_wtxOrdered = wtxOrdered.insert(std::make_pair(wtx.nOrderPos, &wtx));
wtx.nTimeSmart = ComputeTimeSmart(wtx); wtx.nTimeSmart = ComputeTimeSmart(wtx);
AddToSpends(hash); AddToSpends(hash, &batch);
} }
if (!fInsertedNew) if (!fInsertedNew)
@@ -2260,22 +2265,36 @@ bool CWallet::DisplayAddress(const CTxDestination& dest)
return signer_spk_man->DisplayAddress(scriptPubKey, signer); return signer_spk_man->DisplayAddress(scriptPubKey, signer);
} }
void CWallet::LockCoin(const COutPoint& output) bool CWallet::LockCoin(const COutPoint& output, WalletBatch* batch)
{ {
AssertLockHeld(cs_wallet); AssertLockHeld(cs_wallet);
setLockedCoins.insert(output); setLockedCoins.insert(output);
if (batch) {
return batch->WriteLockedUTXO(output);
}
return true;
} }
void CWallet::UnlockCoin(const COutPoint& output) bool CWallet::UnlockCoin(const COutPoint& output, WalletBatch* batch)
{ {
AssertLockHeld(cs_wallet); AssertLockHeld(cs_wallet);
setLockedCoins.erase(output); bool was_locked = setLockedCoins.erase(output);
if (batch && was_locked) {
return batch->EraseLockedUTXO(output);
}
return true;
} }
void CWallet::UnlockAllCoins() bool CWallet::UnlockAllCoins()
{ {
AssertLockHeld(cs_wallet); AssertLockHeld(cs_wallet);
bool success = true;
WalletBatch batch(GetDatabase());
for (auto it = setLockedCoins.begin(); it != setLockedCoins.end(); ++it) {
success &= batch.EraseLockedUTXO(*it);
}
setLockedCoins.clear(); setLockedCoins.clear();
return success;
} }
bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const

View File

@@ -256,8 +256,8 @@ private:
*/ */
typedef std::multimap<COutPoint, uint256> TxSpends; typedef std::multimap<COutPoint, uint256> TxSpends;
TxSpends mapTxSpends GUARDED_BY(cs_wallet); TxSpends mapTxSpends GUARDED_BY(cs_wallet);
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void AddToSpends(const COutPoint& outpoint, const uint256& wtxid, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void AddToSpends(const uint256& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void AddToSpends(const uint256& wtxid, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** /**
* Add a transaction to the wallet, or update it. pIndex and posInBlock should * Add a transaction to the wallet, or update it. pIndex and posInBlock should
@@ -449,9 +449,9 @@ public:
bool DisplayAddress(const CTxDestination& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool DisplayAddress(const CTxDestination& dest) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void LockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool LockCoin(const COutPoint& output, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void UnlockCoin(const COutPoint& output) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool UnlockCoin(const COutPoint& output, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool UnlockAllCoins() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void ListLockedCoins(std::vector<COutPoint>& vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void ListLockedCoins(std::vector<COutPoint>& vOutpts) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/* /*

View File

@@ -40,6 +40,7 @@ const std::string FLAGS{"flags"};
const std::string HDCHAIN{"hdchain"}; const std::string HDCHAIN{"hdchain"};
const std::string KEYMETA{"keymeta"}; const std::string KEYMETA{"keymeta"};
const std::string KEY{"key"}; const std::string KEY{"key"};
const std::string LOCKED_UTXO{"lockedutxo"};
const std::string MASTER_KEY{"mkey"}; const std::string MASTER_KEY{"mkey"};
const std::string MINVERSION{"minversion"}; const std::string MINVERSION{"minversion"};
const std::string NAME{"name"}; const std::string NAME{"name"};
@@ -284,6 +285,16 @@ bool WalletBatch::WriteDescriptorCacheItems(const uint256& desc_id, const Descri
return true; return true;
} }
bool WalletBatch::WriteLockedUTXO(const COutPoint& output)
{
return WriteIC(std::make_pair(DBKeys::LOCKED_UTXO, std::make_pair(output.hash, output.n)), uint8_t{'1'});
}
bool WalletBatch::EraseLockedUTXO(const COutPoint& output)
{
return EraseIC(std::make_pair(DBKeys::LOCKED_UTXO, std::make_pair(output.hash, output.n)));
}
class CWalletScanState { class CWalletScanState {
public: public:
unsigned int nKeys{0}; unsigned int nKeys{0};
@@ -701,6 +712,12 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
wss.m_descriptor_crypt_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), std::make_pair(pubkey, privkey))); wss.m_descriptor_crypt_keys.insert(std::make_pair(std::make_pair(desc_id, pubkey.GetID()), std::make_pair(pubkey, privkey)));
wss.fIsEncrypted = true; wss.fIsEncrypted = true;
} else if (strType == DBKeys::LOCKED_UTXO) {
uint256 hash;
uint32_t n;
ssKey >> hash;
ssKey >> n;
pwallet->LockCoin(COutPoint(hash, n));
} else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE && } else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE &&
strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY && strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY &&
strType != DBKeys::VERSION && strType != DBKeys::SETTINGS && strType != DBKeys::VERSION && strType != DBKeys::SETTINGS &&

View File

@@ -65,6 +65,7 @@ extern const std::string FLAGS;
extern const std::string HDCHAIN; extern const std::string HDCHAIN;
extern const std::string KEY; extern const std::string KEY;
extern const std::string KEYMETA; extern const std::string KEYMETA;
extern const std::string LOCKED_UTXO;
extern const std::string MASTER_KEY; extern const std::string MASTER_KEY;
extern const std::string MINVERSION; extern const std::string MINVERSION;
extern const std::string NAME; extern const std::string NAME;
@@ -250,6 +251,9 @@ public:
bool WriteDescriptorLastHardenedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index); bool WriteDescriptorLastHardenedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index);
bool WriteDescriptorCacheItems(const uint256& desc_id, const DescriptorCache& cache); bool WriteDescriptorCacheItems(const uint256& desc_id, const DescriptorCache& cache);
bool WriteLockedUTXO(const COutPoint& output);
bool EraseLockedUTXO(const COutPoint& output);
/// Write destination data key,value tuple to database /// Write destination data key,value tuple to database
bool WriteDestData(const std::string &address, const std::string &key, const std::string &value); bool WriteDestData(const std::string &address, const std::string &key, const std::string &value);
/// Erase destination data tuple from wallet database /// Erase destination data tuple from wallet database