git / moonbite-core / src/mweb/mweb_wallet.cpp · raw
#include <mweb/mweb_wallet.h>#include <wallet/wallet.h>#include <wallet/coincontrol.h>#include <util/bip32.h>using namespace MWEB;bool Wallet::UpgradeCoins(){ mw::Keychain::Ptr keychain = GetKeychain(); if (!keychain || !keychain->HasSpendSecret()) { return false; } // Loop through transactions and try upgrading output coins for (auto& entry : m_pWallet->mapWallet) { CWalletTx* wtx = &entry.second; RewindOutputs(*wtx->tx); if (wtx->mweb_wtx_info && wtx->mweb_wtx_info->received_coin) { mw::Coin& coin = *wtx->mweb_wtx_info->received_coin; if (!coin.HasSpendKey()) { coin.spend_key = keychain->CalculateOutputKey(coin); // If spend key was populated, update the database and m_coins map. if (coin.HasSpendKey()) { m_coins[coin.output_id] = coin; WalletBatch batch(m_pWallet->GetDatabase()); batch.WriteMWEBCoin(coin); batch.WriteTx(*wtx); } } } } return true;}std::vector<mw::Coin> Wallet::RewindOutputs(const CTransaction& tx){ std::vector<mw::Coin> coins; if (tx.HasMWEBTx()) { for (const Output& output : tx.mweb_tx.m_transaction->GetOutputs()) { mw::Coin mweb_coin; if (RewindOutput(output, mweb_coin)) { coins.push_back(mweb_coin); } } } return coins;}bool Wallet::RewindOutput(const Output& output, mw::Coin& coin){ mw::Keychain::Ptr keychain = GetKeychain(); if (GetCoin(output.GetOutputID(), coin) && coin.IsMine()) { // If the coin has the spend key, it's fully rewound. // If not, try rewinding further if we have the master spend key (i.e. wallet is unlocked). if (coin.HasSpendKey() || !keychain || !keychain->HasSpendSecret()) { return true; } } if (!keychain || !keychain->RewindOutput(output, coin)) { return false; } m_coins[coin.output_id] = coin; WalletBatch(m_pWallet->GetDatabase()).WriteMWEBCoin(coin); return true;}bool Wallet::IsChange(const StealthAddress& address) const{ StealthAddress change_addr; return GetStealthAddress(mw::CHANGE_INDEX, change_addr) && change_addr == address;}bool Wallet::GetStealthAddress(const mw::Coin& coin, StealthAddress& address) const{ if (coin.HasAddress()) { address = *coin.address; return true; } return GetStealthAddress(coin.address_index, address);}bool Wallet::GetStealthAddress(const uint32_t index, StealthAddress& address) const{ mw::Keychain::Ptr keychain = GetKeychain(); if (!keychain || index == mw::UNKNOWN_INDEX || index == mw::CUSTOM_KEY) { return false; } if (keychain->GetSpendSecret().IsNull()) { return false; } address = keychain->GetStealthAddress(index); return true;}void Wallet::LoadToWallet(const mw::Coin& coin){ m_coins[coin.output_id] = coin;}void Wallet::SaveToWallet(const std::vector<mw::Coin>& coins){ WalletBatch batch(m_pWallet->GetDatabase()); for (const mw::Coin& coin : coins) { m_coins[coin.output_id] = coin; batch.WriteMWEBCoin(coin); }}bool Wallet::GetCoin(const mw::Hash& output_id, mw::Coin& coin) const{ auto iter = m_coins.find(output_id); if (iter != m_coins.end()) { coin = iter->second; return true; } coin.Reset(); return false;}mw::Keychain::Ptr Wallet::GetKeychain() const{ auto spk_man = m_pWallet->GetScriptPubKeyMan(OutputType::MWEB, false); return spk_man ? spk_man->GetMWEBKeychain() : nullptr;}