mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-13 07:28:59 +01:00
Allow locked UTXOs to be store in the wallet database
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -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 &&
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user