aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/wallet.cpp')
-rw-r--r--src/wallet/wallet.cpp144
1 files changed, 71 insertions, 73 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 74f36e9abe..c3597aace8 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -36,23 +36,23 @@
#include <boost/algorithm/string/replace.hpp>
static CCriticalSection cs_wallets;
-static std::vector<CWallet*> vpwallets GUARDED_BY(cs_wallets);
+static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
-bool AddWallet(CWallet* wallet)
+bool AddWallet(const std::shared_ptr<CWallet>& wallet)
{
LOCK(cs_wallets);
assert(wallet);
- std::vector<CWallet*>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
+ std::vector<std::shared_ptr<CWallet>>::const_iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i != vpwallets.end()) return false;
vpwallets.push_back(wallet);
return true;
}
-bool RemoveWallet(CWallet* wallet)
+bool RemoveWallet(const std::shared_ptr<CWallet>& wallet)
{
LOCK(cs_wallets);
assert(wallet);
- std::vector<CWallet*>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
+ std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i == vpwallets.end()) return false;
vpwallets.erase(i);
return true;
@@ -64,16 +64,16 @@ bool HasWallets()
return !vpwallets.empty();
}
-std::vector<CWallet*> GetWallets()
+std::vector<std::shared_ptr<CWallet>> GetWallets()
{
LOCK(cs_wallets);
return vpwallets;
}
-CWallet* GetWallet(const std::string& name)
+std::shared_ptr<CWallet> GetWallet(const std::string& name)
{
LOCK(cs_wallets);
- for (CWallet* wallet : vpwallets) {
+ for (const std::shared_ptr<CWallet>& wallet : vpwallets) {
if (wallet->GetName() == name) return wallet;
}
return nullptr;
@@ -191,17 +191,17 @@ CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal)
void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal)
{
// for now we use a fixed keypath scheme of m/0'/0'/k
- CKey key; //master key seed (256bit)
+ CKey seed; //seed (256bit)
CExtKey masterKey; //hd master key
CExtKey accountKey; //key at m/0'
CExtKey chainChildKey; //key at m/0'/0' (external) or m/0'/1' (internal)
CExtKey childKey; //key at m/0'/0'/<n>'
- // try to get the master key
- if (!GetKey(hdChain.masterKeyID, key))
- throw std::runtime_error(std::string(__func__) + ": Master key not found");
+ // try to get the seed
+ if (!GetKey(hdChain.seed_id, seed))
+ throw std::runtime_error(std::string(__func__) + ": seed not found");
- masterKey.SetMaster(key.begin(), key.size());
+ masterKey.SetSeed(seed.begin(), seed.size());
// derive m/0'
// use hardened derivation (child keys >= 0x80000000 are hardened after bip32)
@@ -228,7 +228,7 @@ void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey
}
} while (HaveKey(childKey.key.GetPubKey().GetID()));
secret = childKey.key;
- metadata.hdMasterKeyID = hdChain.masterKeyID;
+ metadata.hd_seed_id = hdChain.seed_id;
// update the chain model in the database
if (!batch.WriteHDChain(hdChain))
throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed");
@@ -549,7 +549,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)
@@ -687,9 +689,9 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Lock();
Unlock(strWalletPassphrase);
- // if we are using HD, replace the HD master key (seed) with a new one
+ // if we are using HD, replace the HD seed with a new one
if (IsHDEnabled()) {
- if (!SetHDMasterKey(GenerateNewHDMasterKey())) {
+ if (!SetHDSeed(GenerateNewSeed())) {
return false;
}
}
@@ -1448,41 +1450,41 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
return nChange;
}
-CPubKey CWallet::GenerateNewHDMasterKey()
+CPubKey CWallet::GenerateNewSeed()
{
CKey key;
key.MakeNewKey(true);
- return DeriveNewMasterHDKey(key);
+ return DeriveNewSeed(key);
}
-CPubKey CWallet::DeriveNewMasterHDKey(const CKey& key)
+CPubKey CWallet::DeriveNewSeed(const CKey& key)
{
int64_t nCreationTime = GetTime();
CKeyMetadata metadata(nCreationTime);
- // calculate the pubkey
- CPubKey pubkey = key.GetPubKey();
- assert(key.VerifyPubKey(pubkey));
+ // calculate the seed
+ CPubKey seed = key.GetPubKey();
+ assert(key.VerifyPubKey(seed));
- // set the hd keypath to "m" -> Master, refers the masterkeyid to itself
- metadata.hdKeypath = "m";
- metadata.hdMasterKeyID = pubkey.GetID();
+ // set the hd keypath to "s" -> Seed, refers the seed to itself
+ metadata.hdKeypath = "s";
+ metadata.hd_seed_id = seed.GetID();
{
LOCK(cs_wallet);
// mem store the metadata
- mapKeyMetadata[pubkey.GetID()] = metadata;
+ mapKeyMetadata[seed.GetID()] = metadata;
// write the key&metadata to the database
- if (!AddKeyPubKey(key, pubkey))
+ if (!AddKeyPubKey(key, seed))
throw std::runtime_error(std::string(__func__) + ": AddKeyPubKey failed");
}
- return pubkey;
+ return seed;
}
-bool CWallet::SetHDMasterKey(const CPubKey& pubkey)
+bool CWallet::SetHDSeed(const CPubKey& seed)
{
LOCK(cs_wallet);
// store the keyid (hash160) together with
@@ -1490,7 +1492,7 @@ bool CWallet::SetHDMasterKey(const CPubKey& pubkey)
// as a hdchain object
CHDChain newHdChain;
newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE;
- newHdChain.masterKeyID = pubkey.GetID();
+ newHdChain.seed_id = seed.GetID();
SetHDChain(newHdChain, false);
return true;
@@ -1508,7 +1510,7 @@ bool CWallet::SetHDChain(const CHDChain& chain, bool memonly)
bool CWallet::IsHDEnabled() const
{
- return !hdChain.masterKeyID.IsNull();
+ return !hdChain.seed_id.IsNull();
}
int64_t CWalletTx::GetTxTime() const
@@ -2073,8 +2075,8 @@ bool CWalletTx::IsTrusted() const
bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
{
- CMutableTransaction tx1 = *this->tx;
- CMutableTransaction tx2 = *_tx.tx;
+ CMutableTransaction tx1 {*this->tx};
+ CMutableTransaction tx2 {*_tx.tx};
for (auto& txin : tx1.vin) txin.scriptSig = CScript();
for (auto& txin : tx2.vin) txin.scriptSig = CScript();
return CTransaction(tx1) == CTransaction(tx2);
@@ -2374,10 +2376,10 @@ void CWallet::AvailableCoins(std::vector<COutput> &vCoins, bool fOnlySafe, const
continue;
}
- bool fSpendableIn = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO);
- bool fSolvableIn = (mine & (ISMINE_SPENDABLE | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO;
+ bool solvable = IsSolvable(*this, pcoin->tx->vout[i].scriptPubKey);
+ bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable));
- vCoins.push_back(COutput(pcoin, i, nDepth, fSpendableIn, fSolvableIn, safeTx));
+ vCoins.push_back(COutput(pcoin, i, nDepth, spendable, solvable, safeTx));
// Checks the sum amount of all UTXO's.
if (nMinimumSumAmount != MAX_MONEY) {
@@ -2606,9 +2608,8 @@ bool CWallet::SignTransaction(CMutableTransaction &tx)
AssertLockHeld(cs_wallet); // mapWallet
// sign the new tx
- CTransaction txNewConst(tx);
int nIn = 0;
- for (const auto& input : tx.vin) {
+ for (auto& input : tx.vin) {
std::map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(input.prevout.hash);
if(mi == mapWallet.end() || input.prevout.n >= mi->second.tx->vout.size()) {
return false;
@@ -2616,10 +2617,10 @@ bool CWallet::SignTransaction(CMutableTransaction &tx)
const CScript& scriptPubKey = mi->second.tx->vout[input.prevout.n].scriptPubKey;
const CAmount& amount = mi->second.tx->vout[input.prevout.n].nValue;
SignatureData sigdata;
- if (!ProduceSignature(*this, TransactionSignatureCreator(&txNewConst, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
+ if (!ProduceSignature(*this, MutableTransactionSignatureCreator(&tx, nIn, amount, SIGHASH_ALL), scriptPubKey, sigdata)) {
return false;
}
- UpdateTransaction(tx, nIn, sigdata);
+ UpdateInput(input, sigdata);
nIn++;
}
return true;
@@ -3038,19 +3039,18 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CTransac
if (sign)
{
- CTransaction txNewConst(txNew);
int nIn = 0;
for (const auto& coin : selected_coins)
{
const CScript& scriptPubKey = coin.txout.scriptPubKey;
SignatureData sigdata;
- if (!ProduceSignature(*this, TransactionSignatureCreator(&txNewConst, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata))
+ if (!ProduceSignature(*this, MutableTransactionSignatureCreator(&txNew, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata))
{
strFailReason = _("Signing transaction failed");
return false;
} else {
- UpdateTransaction(txNew, nIn, sigdata);
+ UpdateInput(txNew.vin.at(nIn), sigdata);
}
nIn++;
@@ -3199,8 +3199,6 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
if (nLoadWalletRet != DBErrors::LOAD_OK)
return nLoadWalletRet;
- uiInterface.LoadWallet(this);
-
return DBErrors::LOAD_OK;
}
@@ -3427,7 +3425,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
return true;
}
-void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
+bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
{
nIndex = -1;
keypool.vchPubKey = CPubKey();
@@ -3438,11 +3436,13 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
TopUpKeyPool();
bool fReturningInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && fRequestedInternal;
- std::set<int64_t>& setKeyPool = set_pre_split_keypool.empty() ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
+ bool use_split_keypool = set_pre_split_keypool.empty();
+ std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
// Get the oldest key
- if(setKeyPool.empty())
- return;
+ if (setKeyPool.empty()) {
+ return false;
+ }
WalletBatch batch(*database);
@@ -3456,14 +3456,17 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
}
// If the key was pre-split keypool, we don't care about what type it is
- if (set_pre_split_keypool.size() == 0 && keypool.fInternal != fReturningInternal) {
+ if (use_split_keypool && keypool.fInternal != fReturningInternal) {
throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified");
}
+ if (!keypool.vchPubKey.IsValid()) {
+ throw std::runtime_error(std::string(__func__) + ": keypool entry invalid");
+ }
- assert(keypool.vchPubKey.IsValid());
m_pool_key_to_index.erase(keypool.vchPubKey.GetID());
LogPrintf("keypool reserve %d\n", nIndex);
}
+ return true;
}
void CWallet::KeepKey(int64_t nIndex)
@@ -3496,10 +3499,8 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal)
CKeyPool keypool;
{
LOCK(cs_wallet);
- int64_t nIndex = 0;
- ReserveKeyFromKeyPool(nIndex, keypool, internal);
- if (nIndex == -1)
- {
+ int64_t nIndex;
+ if (!ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
if (IsLocked()) return false;
WalletBatch batch(*database);
result = GenerateNewKey(batch, internal);
@@ -3701,12 +3702,10 @@ bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool internal)
if (nIndex == -1)
{
CKeyPool keypool;
- pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal);
- if (nIndex != -1)
- vchPubKey = keypool.vchPubKey;
- else {
+ if (!pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
return false;
}
+ vchPubKey = keypool.vchPubKey;
fInternal = keypool.fInternal;
}
assert(vchPubKey.IsValid());
@@ -4036,7 +4035,7 @@ bool CWallet::Verify(std::string wallet_file, bool salvage_wallet, std::string&
return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, error_string);
}
-CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path)
+std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(const std::string& name, const fs::path& path)
{
const std::string& walletFile = name;
@@ -4058,10 +4057,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
- // Make a temporary wallet unique pointer so memory doesn't get leaked if
- // wallet creation fails.
- auto temp_wallet = MakeUnique<CWallet>(name, WalletDatabase::Create(path));
- CWallet* walletInstance = temp_wallet.get();
+ std::shared_ptr<CWallet> walletInstance = std::make_shared<CWallet>(name, WalletDatabase::Create(path));
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
@@ -4090,6 +4086,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
}
}
+ uiInterface.LoadWallet(walletInstance);
+
int prev_version = walletInstance->nWalletVersion;
if (gArgs.GetBoolArg("-upgradewallet", fFirstRun))
{
@@ -4128,8 +4126,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
walletInstance->SetMinVersion(FEATURE_HD);
// generate a new master key
- CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey();
- if (!walletInstance->SetHDMasterKey(masterPubKey)) {
+ CPubKey masterPubKey = walletInstance->GenerateNewSeed();
+ if (!walletInstance->SetHDSeed(masterPubKey)) {
throw std::runtime_error(std::string(__func__) + ": Storing master key failed");
}
hd_upgrade = true;
@@ -4162,10 +4160,10 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
}
walletInstance->SetMinVersion(FEATURE_LATEST);
- // generate a new master key
- CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey();
- if (!walletInstance->SetHDMasterKey(masterPubKey))
- throw std::runtime_error(std::string(__func__) + ": Storing master key failed");
+ // generate a new seed
+ CPubKey seed = walletInstance->GenerateNewSeed();
+ if (!walletInstance->SetHDSeed(seed))
+ throw std::runtime_error(std::string(__func__) + ": Storing HD seed failed");
// Top up the keypool
if (!walletInstance->TopUpKeyPool()) {
@@ -4302,7 +4300,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
nStart = GetTimeMillis();
{
- WalletRescanReserver reserver(walletInstance);
+ WalletRescanReserver reserver(walletInstance.get());
if (!reserver.reserve()) {
InitError(_("Failed to rescan the wallet during initialization"));
return nullptr;
@@ -4340,7 +4338,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path&
}
// Register with the validation interface. It's ok to do this after rescan since we're still holding cs_main.
- RegisterValidationInterface(temp_wallet.release());
+ RegisterValidationInterface(walletInstance.get());
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));