mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-10 10:52:31 -05:00
Merge bitcoin/bitcoin#25656: refactor: wallet: return util::Result from GetReservedDestination
methods
76b3c37fcb
refactor: wallet: return util::Result from `GetReservedDestination` methods (Sebastian Falbesoner) Pull request description: This PR is a follow-up to #25218, as suggested in comment https://github.com/bitcoin/bitcoin/pull/25218#discussion_r907710067. The interfaces of the methods `ReserveDestination::GetReservedDestination`, `{Legacy,Descriptor,}ScriptPubKeyMan::GetReservedDestination` are improved by returning `util::Result<CTxDestination>` instead of `bool` in order to get rid of the two `CTxDestination&` and `bilingual_str&` out-parameters. ACKs for top commit: furszy: ACK76b3c37f
Tree-SHA512: bf15560a88d645bcf8768024013d36012cd65caaa4a613e8a055dfd8f29cb4a219c19084606992bad177920cdca3a732ec168e9b9526f9295491f2cf79cc6815
This commit is contained in:
commit
a6fc293c0a
5 changed files with 26 additions and 40 deletions
|
@ -292,26 +292,22 @@ bool LegacyScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, WalletBat
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
|
util::Result<CTxDestination> LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
|
||||||
{
|
{
|
||||||
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
|
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
|
||||||
error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");
|
return util::Error{_("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types")};
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
assert(type != OutputType::BECH32M);
|
assert(type != OutputType::BECH32M);
|
||||||
|
|
||||||
LOCK(cs_KeyStore);
|
LOCK(cs_KeyStore);
|
||||||
if (!CanGetAddresses(internal)) {
|
if (!CanGetAddresses(internal)) {
|
||||||
error = _("Error: Keypool ran out, please call keypoolrefill first");
|
return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
|
if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
|
||||||
error = _("Error: Keypool ran out, please call keypoolrefill first");
|
return util::Error{_("Error: Keypool ran out, please call keypoolrefill first")};
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
address = GetDestinationForKey(keypool.vchPubKey, type);
|
return GetDestinationForKey(keypool.vchPubKey, type);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal)
|
bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal)
|
||||||
|
@ -1760,17 +1756,12 @@ bool DescriptorScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, Walle
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
|
util::Result<CTxDestination> DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
|
||||||
{
|
{
|
||||||
LOCK(cs_desc_man);
|
LOCK(cs_desc_man);
|
||||||
auto op_dest = GetNewDestination(type);
|
auto op_dest = GetNewDestination(type);
|
||||||
index = m_wallet_descriptor.next_index - 1;
|
index = m_wallet_descriptor.next_index - 1;
|
||||||
if (op_dest) {
|
return op_dest;
|
||||||
address = *op_dest;
|
|
||||||
} else {
|
|
||||||
error = util::ErrorString(op_dest);
|
|
||||||
}
|
|
||||||
return bool(op_dest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CTxDestination& addr)
|
void DescriptorScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CTxDestination& addr)
|
||||||
|
|
|
@ -179,7 +179,7 @@ public:
|
||||||
virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) { return false; }
|
virtual bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) { return false; }
|
||||||
virtual bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) { return false; }
|
virtual bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) { return false; }
|
||||||
|
|
||||||
virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) { return false; }
|
virtual util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) { return util::Error{Untranslated("Not supported")}; }
|
||||||
virtual void KeepDestination(int64_t index, const OutputType& type) {}
|
virtual void KeepDestination(int64_t index, const OutputType& type) {}
|
||||||
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
|
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ public:
|
||||||
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
|
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
|
||||||
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
|
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
|
||||||
|
|
||||||
bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) override;
|
util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
|
||||||
void KeepDestination(int64_t index, const OutputType& type) override;
|
void KeepDestination(int64_t index, const OutputType& type) override;
|
||||||
void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
|
void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
|
||||||
|
|
||||||
|
@ -576,7 +576,7 @@ public:
|
||||||
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
|
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
|
||||||
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
|
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
|
||||||
|
|
||||||
bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) override;
|
util::Result<CTxDestination> GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool) override;
|
||||||
void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) override;
|
void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) override;
|
||||||
|
|
||||||
// Tops up the descriptor cache and m_map_script_pub_keys. The cache is stored in the wallet file
|
// Tops up the descriptor cache and m_map_script_pub_keys. The cache is stored in the wallet file
|
||||||
|
|
|
@ -814,11 +814,13 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
|
||||||
// Reserve a new key pair from key pool. If it fails, provide a dummy
|
// Reserve a new key pair from key pool. If it fails, provide a dummy
|
||||||
// destination in case we don't need change.
|
// destination in case we don't need change.
|
||||||
CTxDestination dest;
|
CTxDestination dest;
|
||||||
bilingual_str dest_err;
|
auto op_dest = reservedest.GetReservedDestination(true);
|
||||||
if (!reservedest.GetReservedDestination(dest, true, dest_err)) {
|
if (!op_dest) {
|
||||||
error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + dest_err;
|
error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + util::ErrorString(op_dest);
|
||||||
|
} else {
|
||||||
|
dest = *op_dest;
|
||||||
|
scriptChange = GetScriptForDestination(dest);
|
||||||
}
|
}
|
||||||
scriptChange = GetScriptForDestination(dest);
|
|
||||||
// A valid destination implies a change script (and
|
// A valid destination implies a change script (and
|
||||||
// vice-versa). An empty change script will abort later, if the
|
// vice-versa). An empty change script will abort later, if the
|
||||||
// change keypool ran out, but change is required.
|
// change keypool ran out, but change is required.
|
||||||
|
|
|
@ -2359,15 +2359,11 @@ util::Result<CTxDestination> CWallet::GetNewChangeDestination(const OutputType t
|
||||||
{
|
{
|
||||||
LOCK(cs_wallet);
|
LOCK(cs_wallet);
|
||||||
|
|
||||||
CTxDestination dest;
|
|
||||||
bilingual_str error;
|
|
||||||
ReserveDestination reservedest(this, type);
|
ReserveDestination reservedest(this, type);
|
||||||
if (!reservedest.GetReservedDestination(dest, true, error)) {
|
auto op_dest = reservedest.GetReservedDestination(true);
|
||||||
return util::Error{error};
|
if (op_dest) reservedest.KeepDestination();
|
||||||
}
|
|
||||||
|
|
||||||
reservedest.KeepDestination();
|
return op_dest;
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int64_t> CWallet::GetOldestKeyPoolTime() const
|
std::optional<int64_t> CWallet::GetOldestKeyPoolTime() const
|
||||||
|
@ -2437,27 +2433,24 @@ std::set<std::string> CWallet::ListAddrBookLabels(const std::string& purpose) co
|
||||||
return label_set;
|
return label_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal, bilingual_str& error)
|
util::Result<CTxDestination> ReserveDestination::GetReservedDestination(bool internal)
|
||||||
{
|
{
|
||||||
m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
|
m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
|
||||||
if (!m_spk_man) {
|
if (!m_spk_man) {
|
||||||
error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type));
|
return util::Error{strprintf(_("Error: No %s addresses available."), FormatOutputType(type))};
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (nIndex == -1)
|
if (nIndex == -1)
|
||||||
{
|
{
|
||||||
m_spk_man->TopUp();
|
m_spk_man->TopUp();
|
||||||
|
|
||||||
CKeyPool keypool;
|
CKeyPool keypool;
|
||||||
if (!m_spk_man->GetReservedDestination(type, internal, address, nIndex, keypool, error)) {
|
auto op_address = m_spk_man->GetReservedDestination(type, internal, nIndex, keypool);
|
||||||
return false;
|
if (!op_address) return op_address;
|
||||||
}
|
address = *op_address;
|
||||||
fInternal = keypool.fInternal;
|
fInternal = keypool.fInternal;
|
||||||
}
|
}
|
||||||
dest = address;
|
return address;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReserveDestination::KeepDestination()
|
void ReserveDestination::KeepDestination()
|
||||||
|
|
|
@ -191,7 +191,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Reserve an address
|
//! Reserve an address
|
||||||
bool GetReservedDestination(CTxDestination& pubkey, bool internal, bilingual_str& error);
|
util::Result<CTxDestination> GetReservedDestination(bool internal);
|
||||||
//! Return reserved address
|
//! Return reserved address
|
||||||
void ReturnDestination();
|
void ReturnDestination();
|
||||||
//! Keep the address. Do not return it's key to the keypool when this object goes out of scope
|
//! Keep the address. Do not return it's key to the keypool when this object goes out of scope
|
||||||
|
|
Loading…
Add table
Reference in a new issue