Merge b1a672d158 into merged_master (Bitcoin PR bitcoin/bitcoin#22337)

This commit is contained in:
Byron Hambly 2023-04-07 11:14:41 +00:00
commit a20c67310c
17 changed files with 92 additions and 80 deletions

View file

@ -22,6 +22,7 @@
#include <univalue.h>
#include <util/rbf.h>
#include <util/strencodings.h>
#include <util/translation.h>
#include <validation.h>
template<typename T_tx>
@ -531,7 +532,7 @@ void ParsePrevouts(const UniValue& prevTxsUnival, FillableSigningProvider* keyst
}
// ELEMENTS: check whether pegin inputs make sense against the current fedpegscript
bool ValidateTransactionPeginInputs(const CMutableTransaction& mtx, const CBlockIndex* active_chain_tip, std::map<int, std::string>& input_errors)
bool ValidateTransactionPeginInputs(const CMutableTransaction& mtx, const CBlockIndex* active_chain_tip, std::map<int, bilingual_str>& input_errors)
{
const auto& fedpegscripts = GetValidFedpegScripts(active_chain_tip, Params().GetConsensus(), true /* nextblock_validation */);
// Track an immature peg-in that's otherwise valid, give warning
@ -541,7 +542,7 @@ bool ValidateTransactionPeginInputs(const CMutableTransaction& mtx, const CBlock
const CTxIn& txin = mtx.vin[i];
std::string err;
if (txin.m_is_pegin && (mtx.witness.vtxinwit.size() <= i || !IsValidPeginWitness(mtx.witness.vtxinwit[i].m_pegin_witness, fedpegscripts, txin.prevout, err, false))) {
input_errors[i] = "Peg-in input has invalid proof.";
input_errors[i] = _("Peg-in input has invalid proof.");
continue;
}
// Report warning about immature peg-in though
@ -559,23 +560,23 @@ void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
int nHashType = ParseSighashString(hashType);
// Script verification errors
std::map<int, std::string> input_errors;
std::map<int, bilingual_str> input_errors;
bool immature_pegin = ValidateTransactionPeginInputs(mtx, active_chain_tip, input_errors);
bool complete = SignTransaction(mtx, keystore, coins, nHashType, Params().HashGenesisBlock(), input_errors);
SignTransactionResultToJSON(mtx, complete, coins, input_errors, immature_pegin, result);
}
void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, const std::map<int, std::string>& input_errors, bool immature_pegin, UniValue& result)
void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, const std::map<int, bilingual_str>& input_errors, bool immature_pegin, UniValue& result)
{
// Make errors UniValue
UniValue vErrors(UniValue::VARR);
for (const auto& err_pair : input_errors) {
if (err_pair.second == "Missing amount") {
if (err_pair.second.original == "Missing amount") {
// This particular error needs to be an exception for some reason
throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Missing amount for %s", coins.at(mtx.vin.at(err_pair.first).prevout).out.ToString()));
}
TxInErrorToJSON(mtx.vin.at(err_pair.first), mtx.witness.vtxinwit.at(err_pair.first), vErrors, err_pair.second);
TxInErrorToJSON(mtx.vin.at(err_pair.first), mtx.witness.vtxinwit.at(err_pair.first), vErrors, err_pair.second.original);
}
result.pushKV("hex", EncodeHexTx(CTransaction(mtx)));
@ -590,4 +591,3 @@ void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const
result.pushKV("warning", "Possibly immature peg-in input(s) detected, signed anyways.");
}
}

View file

@ -17,6 +17,7 @@
#include <pubkey.h>
#include <psbt.h>
struct bilingual_str;
class FillableSigningProvider;
class UniValue;
struct CMutableTransaction;
@ -34,7 +35,7 @@ class SigningProvider;
* @param result JSON object where signed transaction results accumulate
*/
void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType, UniValue& result, const CBlockIndex* active_chain_tip);
void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, const std::map<int, std::string>& input_errors, bool immature_pegin, UniValue& result);
void SignTransactionResultToJSON(CMutableTransaction& mtx, bool complete, const std::map<COutPoint, Coin>& coins, const std::map<int, bilingual_str>& input_errors, bool immature_pegin, UniValue& result);
/**
* Parse a prevtxs UniValue array and get the map of coins from it
@ -55,6 +56,6 @@ void CreatePegInInput(CMutableTransaction& mtx, uint32_t input_idx, CTransaction
void CreatePegInInput(CMutableTransaction& mtx, uint32_t input_idx, Sidechain::Bitcoin::CTransactionRef& tx_btc, Sidechain::Bitcoin::CMerkleBlock& merkle_block, const std::set<CScript>& claim_scripts, const std::vector<unsigned char>& txData, const std::vector<unsigned char>& txOutProofData, const CBlockIndex* active_chain_tip);
/** Check a peg-in input against the current fedpeg parameters */
bool ValidateTransactionPeginInputs(const CMutableTransaction& mtx, const CBlockIndex* active_chain_tip, std::map<int, std::string>& input_errors);
bool ValidateTransactionPeginInputs(const CMutableTransaction& mtx, const CBlockIndex* active_chain_tip, std::map<int, bilingual_str>& input_errors);
#endif // BITCOIN_RPC_RAWTRANSACTION_UTIL_H

View file

@ -13,6 +13,7 @@
#include <script/signingprovider.h>
#include <script/standard.h>
#include <uint256.h>
#include <util/translation.h>
#include <util/vector.h>
#include <chainparams.h>
@ -653,7 +654,7 @@ bool IsSegWitOutput(const SigningProvider& provider, const CScript& script)
return false;
}
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, int nHashType, const uint256& hash_genesis_block, std::map<int, std::string>& input_errors)
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, int nHashType, const uint256& hash_genesis_block, std::map<int, bilingual_str>& input_errors)
{
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
@ -692,7 +693,7 @@ bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
} else {
auto coin = coins.find(txin.prevout);
if (coin == coins.end() || coin->second.IsSpent()) {
input_errors[i] = "Input not found or already spent";
input_errors[i] = _("Input not found or already spent");
continue;
}
prevTxOut = coin->second.out;
@ -711,7 +712,7 @@ bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
// amount must be specified for valid segwit signature
if (amount.IsExplicit() && amount.GetAmount() == MAX_MONEY && !mtx.witness.vtxinwit[i].scriptWitness.IsNull()) {
input_errors[i] = "Missing amount";
input_errors[i] = _("Missing amount");
continue;
}
@ -719,12 +720,12 @@ bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore,
if (!VerifyScript(txin.scriptSig, prevPubKey, &inWitness.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount, txdata, MissingDataBehavior::FAIL), &serror)) {
if (serror == SCRIPT_ERR_INVALID_STACK_OPERATION) {
// Unable to sign input and verification failed (possible attempt to partially sign).
input_errors[i] = "Unable to sign input, invalid stack size (possibly missing key)";
input_errors[i] = Untranslated("Unable to sign input, invalid stack size (possibly missing key)");
} else if (serror == SCRIPT_ERR_SIG_NULLFAIL) {
// Verification failed (possibly due to insufficient signatures).
input_errors[i] = "CHECK(MULTI)SIG failing with non-zero signature (possibly need more signatures)";
input_errors[i] = Untranslated("CHECK(MULTI)SIG failing with non-zero signature (possibly need more signatures)");
} else {
input_errors[i] = ScriptErrorString(serror);
input_errors[i] = Untranslated(ScriptErrorString(serror));
}
} else {
// If this input succeeds, make sure there is no error set for it

View file

@ -21,6 +21,7 @@ class CScript;
class CTransaction;
class SigningProvider;
struct bilingual_str;
struct CMutableTransaction;
/** Interface for signature creators. */
@ -104,6 +105,6 @@ bool IsSolvable(const SigningProvider& provider, const CScript& script);
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script);
/** Sign the CMutableTransaction */
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* provider, const std::map<COutPoint, Coin>& coins, int sighash, const uint256& hash_genesis_block, std::map<int, std::string>& input_errors);
bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* provider, const std::map<COutPoint, Coin>& coins, int sighash, const uint256& hash_genesis_block, std::map<int, bilingual_str>& input_errors);
#endif // BITCOIN_SCRIPT_SIGN_H

View file

@ -14,6 +14,7 @@
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h>
#include <util/translation.h>
#include <cassert>
#include <cstdint>
@ -138,7 +139,7 @@ FUZZ_TARGET_INIT(script_sign, initialize_script_sign)
}
coins[*outpoint] = *coin;
}
std::map<int, std::string> input_errors;
std::map<int, bilingual_str> input_errors;
auto genesis_hash = ConsumeUInt256(fuzzed_data_provider);
(void)SignTransaction(sign_transaction_tx_to, &provider, coins, fuzzed_data_provider.ConsumeIntegral<int>(), genesis_hash, input_errors);
}

View file

@ -317,7 +317,7 @@ CMutableTransaction TestChain100Setup::CreateValidMempoolTransaction(CTransactio
input_coins.insert({outpoint_to_spend, utxo_to_spend});
// - Default signature hashing type
int nHashType = SIGHASH_ALL;
std::map<int, std::string> input_errors;
std::map<int, bilingual_str> input_errors;
assert(SignTransaction(mempool_txn, &keystore, input_coins, nHashType, Params().HashGenesisBlock(), input_errors));
// If submit=true, add transaction to the mempool.

View file

@ -8,6 +8,7 @@
#include <outputtype.h>
#include <script/standard.h>
#ifdef ENABLE_WALLET
#include <util/translation.h>
#include <wallet/wallet.h>
#endif
@ -18,7 +19,7 @@ std::string getnewaddress(CWallet& w)
{
constexpr auto output_type = OutputType::BECH32;
CTxDestination dest;
std::string error;
bilingual_str error;
if (!w.GetNewDestination(output_type, "", dest, error)) assert(false);
return EncodeDestination(dest);

View file

@ -28,6 +28,12 @@ struct bilingual_str {
{
return original.empty();
}
void clear()
{
original.clear();
translated.clear();
}
};
inline bilingual_str operator+(bilingual_str lhs, const bilingual_str& rhs)

View file

@ -16,6 +16,7 @@
#include <uint256.h>
#include <util/check.h>
#include <util/system.h>
#include <util/translation.h>
#include <util/ui_change_type.h>
#include <wallet/context.h>
#include <wallet/feebumper.h>
@ -142,7 +143,7 @@ public:
bool getNewDestination(const OutputType type, const std::string label, CTxDestination& dest, bool add_blinding_key = false) override
{
LOCK(m_wallet->cs_wallet);
std::string error;
bilingual_str error;
return m_wallet->GetNewDestination(type, label, dest, error, add_blinding_key);
}
bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) override

View file

@ -310,10 +310,10 @@ static RPCHelpMan getnewaddress()
}
CTxDestination dest;
std::string error;
bilingual_str error;
bool add_blinding_key = force_blind || gArgs.GetBoolArg("-blindedaddresses", g_con_elementsmode);
if (!pwallet->GetNewDestination(output_type, label, dest, error, add_blinding_key)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error);
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
}
return EncodeDestination(dest);
@ -364,10 +364,10 @@ static RPCHelpMan getrawchangeaddress()
}
CTxDestination dest;
std::string error;
bilingual_str error;
bool add_blinding_key = force_blind || gArgs.GetBoolArg("-blindedaddresses", g_con_elementsmode);
if (!pwallet->GetNewChangeDestination(output_type, dest, error, add_blinding_key)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error);
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
}
return EncodeDestination(dest);
},
@ -3728,7 +3728,7 @@ RPCHelpMan signrawtransactionwithwallet()
int nHashType = ParseSighashString(request.params[2]);
// Script verification errors
std::map<int, std::string> input_errors;
std::map<int, bilingual_str> input_errors;
bool immature_pegin = ValidateTransactionPeginInputs(mtx, pwallet->chain().getTip(), input_errors);
bool complete = pwallet->SignTransaction(mtx, coins, nHashType, input_errors);
@ -5369,9 +5369,9 @@ static RPCHelpMan getpeginaddress()
// Use native witness destination
CTxDestination dest;
std::string error;
bilingual_str error;
if (!pwallet->GetNewDestination(OutputType::BECH32, "", dest, error)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error);
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
}
CScript dest_script = GetScriptForDestination(dest);
@ -6013,9 +6013,9 @@ static UniValue createrawpegin(const JSONRPCRequest& request, T_tx_ref& txBTCRef
// Generate a new key that is added to wallet
CTxDestination wpkhash;
std::string error;
bilingual_str error;
if (!pwallet->GetNewDestination(OutputType::BECH32, "", wpkhash, error)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error);
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
}
// Get value for output
@ -6624,7 +6624,7 @@ static RPCHelpMan issueasset()
pwallet->TopUpKeyPool();
// Generate a new key that is added to wallet
std::string error;
bilingual_str error;
CPubKey newKey;
CTxDestination asset_dest;
CTxDestination token_dest;
@ -6633,13 +6633,13 @@ static RPCHelpMan issueasset()
if (nAmount > 0) {
if (!pwallet->GetNewDestination(OutputType::BECH32, "", asset_dest, error)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error);
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
}
asset_dest_blindpub = pwallet->GetBlindingPubKey(GetScriptForDestination(asset_dest));
}
if (nTokens > 0) {
if (!pwallet->GetNewDestination(OutputType::BECH32, "", token_dest, error)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error);
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
}
token_dest_blindpub = pwallet->GetBlindingPubKey(GetScriptForDestination(token_dest));
}
@ -6731,17 +6731,17 @@ static RPCHelpMan reissueasset()
}
// Add destination for the to-be-created asset
std::string error;
bilingual_str error;
CTxDestination asset_dest;
if (!pwallet->GetNewDestination(OutputType::BECH32, "", asset_dest, error)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error);
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
}
CPubKey asset_dest_blindpub = pwallet->GetBlindingPubKey(GetScriptForDestination(asset_dest));
// Add destination for tokens we are moving
CTxDestination token_dest;
if (!pwallet->GetNewDestination(OutputType::BECH32, "", token_dest, error)) {
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error);
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, error.original);
}
CPubKey token_dest_blindpub = pwallet->GetBlindingPubKey(GetScriptForDestination(token_dest));

View file

@ -20,10 +20,10 @@
//! Value for the first BIP 32 hardened derivation. Can be used as a bit mask and as a value. See BIP 32 for more details.
const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000;
bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error)
bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error)
{
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types").translated;
error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");
return false;
}
assert(type != OutputType::BECH32M);
@ -34,7 +34,7 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestinat
// Generate a new key that is added to wallet
CPubKey new_key;
if (!GetKeyFromPool(new_key, type)) {
error = _("Error: Keypool ran out, please call keypoolrefill first").translated;
error = _("Error: Keypool ran out, please call keypoolrefill first");
return false;
}
LearnRelatedScripts(new_key, type);
@ -302,22 +302,22 @@ bool LegacyScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, WalletBat
return true;
}
bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, std::string& error)
bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
{
if (LEGACY_OUTPUT_TYPES.count(type) == 0) {
error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types").translated;
error = _("Error: Legacy wallets only support the \"legacy\", \"p2sh-segwit\", and \"bech32\" address types");
return false;
}
assert(type != OutputType::BECH32M);
LOCK(cs_KeyStore);
if (!CanGetAddresses(internal)) {
error = _("Error: Keypool ran out, please call keypoolrefill first").translated;
error = _("Error: Keypool ran out, please call keypoolrefill first");
return false;
}
if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
error = _("Error: Keypool ran out, please call keypoolrefill first").translated;
error = _("Error: Keypool ran out, please call keypoolrefill first");
return false;
}
address = GetDestinationForKey(keypool.vchPubKey, type);
@ -599,7 +599,7 @@ bool LegacyScriptPubKeyMan::CanProvide(const CScript& script, SignatureData& sig
}
}
bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
bool LegacyScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
{
return ::SignTransaction(tx, this, coins, sighash, Params().HashGenesisBlock(), input_errors);
}
@ -1619,11 +1619,11 @@ std::set<CKeyID> LegacyScriptPubKeyMan::GetKeys() const
return set_address;
}
bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error)
bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error)
{
// Returns true if this descriptor supports getting new addresses. Conditions where we may be unable to fetch them (e.g. locked) are caught later
if (!CanGetAddresses()) {
error = "No addresses available";
error = _("No addresses available");
return false;
}
{
@ -1642,12 +1642,12 @@ bool DescriptorScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDest
std::vector<CScript> scripts_temp;
if (m_wallet_descriptor.range_end <= m_max_cached_index && !TopUp(1)) {
// We can't generate anymore keys
error = "Error: Keypool ran out, please call keypoolrefill first";
error = _("Error: Keypool ran out, please call keypoolrefill first");
return false;
}
if (!m_wallet_descriptor.descriptor->ExpandFromCache(m_wallet_descriptor.next_index, m_wallet_descriptor.cache, scripts_temp, out_keys)) {
// We can't generate anymore keys
error = "Error: Keypool ran out, please call keypoolrefill first";
error = _("Error: Keypool ran out, please call keypoolrefill first");
return false;
}
@ -1727,7 +1727,7 @@ bool DescriptorScriptPubKeyMan::Encrypt(const CKeyingMaterial& master_key, Walle
return true;
}
bool DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, std::string& error)
bool DescriptorScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error)
{
LOCK(cs_desc_man);
bool result = GetNewDestination(type, address, error);
@ -2052,7 +2052,7 @@ bool DescriptorScriptPubKeyMan::CanProvide(const CScript& script, SignatureData&
return IsMine(script);
}
bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
{
std::unique_ptr<FlatSigningProvider> keys = std::make_unique<FlatSigningProvider>();
for (const auto& coin_pair : coins) {

View file

@ -174,14 +174,14 @@ protected:
public:
explicit ScriptPubKeyMan(WalletStorage& storage) : m_storage(storage) {}
virtual ~ScriptPubKeyMan() {};
virtual bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) { return false; }
virtual bool GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error) { return false; }
virtual isminetype IsMine(const CScript& script) const { return ISMINE_NO; }
//! Check that the given decryption key is valid for this ScriptPubKeyMan, i.e. it decrypts all of the keys handled by it.
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 GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, std::string& error) { return false; }
virtual bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) { return false; }
virtual void KeepDestination(int64_t index, const OutputType& type) {}
virtual void ReturnDestination(int64_t index, bool internal, const CTxDestination& addr) {}
@ -230,7 +230,7 @@ public:
virtual bool CanProvide(const CScript& script, SignatureData& sigdata) { return false; }
/** Creates new signatures and adds them to the transaction. Returns whether all inputs were signed */
virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const { return false; }
virtual bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const { return false; }
/** Sign a message with the given script */
virtual SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const { return SigningResult::SIGNING_FAILED; };
/** Adds script and derivation path information to a PSBT, and optionally signs it. */
@ -355,13 +355,13 @@ private:
public:
using ScriptPubKeyMan::ScriptPubKeyMan;
bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) override;
bool GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error) override;
isminetype IsMine(const CScript& script) const override;
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, std::string& error) override;
bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) override;
void KeepDestination(int64_t index, const OutputType& type) override;
void ReturnDestination(int64_t index, bool internal, const CTxDestination&) override;
@ -396,7 +396,7 @@ public:
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
TransactionError FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr) const override;
@ -565,13 +565,13 @@ public:
mutable RecursiveMutex cs_desc_man;
bool GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error) override;
bool GetNewDestination(const OutputType type, CTxDestination& dest, bilingual_str& error) override;
isminetype IsMine(const CScript& script) const override;
bool CheckDecryptionKey(const CKeyingMaterial& master_key, bool accept_no_keys = false) override;
bool Encrypt(const CKeyingMaterial& master_key, WalletBatch* batch) override;
bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, std::string& error) override;
bool GetReservedDestination(const OutputType type, bool internal, CTxDestination& address, int64_t& index, CKeyPool& keypool, bilingual_str& error) 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
@ -607,7 +607,7 @@ public:
bool CanProvide(const CScript& script, SignatureData& sigdata) override;
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const override;
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const override;
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const override;
TransactionError FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, int sighash_type = 1 /* SIGHASH_ALL */, bool sign = true, bool bip32derivs = false, int* n_signed = nullptr) const override;

View file

@ -887,7 +887,7 @@ bool CWallet::CreateTransactionInternal(
std::map<CAsset, std::pair<int, CScript>> mapScriptChange;
// For manually set change, we need to use the blinding pubkey associated
// with the manually-set address rather than generating one from the wallet
std::map<CAsset, std::optional<CPubKey> > mapBlindingKeyChange;
std::map<CAsset, std::optional<CPubKey>> mapBlindingKeyChange;
// coin control: send change to custom address
if (coin_control.destChange.size() > 0) {
@ -914,12 +914,12 @@ bool CWallet::CreateTransactionInternal(
// Reserve a new key pair from key pool. If it fails, provide a dummy
// destination in case we don't need change.
CTxDestination dest;
std::string dest_err;
bilingual_str dest_err;
if (index >= reservedest.size() || !reservedest[index]->GetReservedDestination(dest, true, dest_err)) {
if (dest_err.empty()) {
dest_err = "Please call keypoolrefill first";
dest_err = _("Please call keypoolrefill first");
}
error = strprintf(_("Transaction needs a change address, but we can't generate it. %s"), dest_err);
error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + dest_err;
// ELEMENTS: We need to put a dummy destination here. Core uses an empty script
// but we can't because empty scripts indicate fees (which trigger assertion
// failures in `BlindTransaction`). We also set the index to -1, indicating
@ -954,12 +954,12 @@ bool CWallet::CreateTransactionInternal(
}
CTxDestination dest;
std::string dest_err;
bilingual_str dest_err;
if (index >= reservedest.size() || !reservedest[index]->GetReservedDestination(dest, true, dest_err)) {
if (dest_err.empty()) {
dest_err = "Keypool ran out, please call keypoolrefill first";
dest_err = _("Keypool ran out, please call keypoolrefill first");
}
error = strprintf(_("Transaction needs a change address, but we can't generate it. %s"), dest_err);
error = _("Transaction needs a change address, but we can't generate it.") + Untranslated(" ") + dest_err;
return false;
}

View file

@ -7,6 +7,7 @@
#include <primitives/transaction.h>
#include <random.h>
#include <test/util/setup_common.h>
#include <util/translation.h>
#include <wallet/coincontrol.h>
#include <wallet/coinselection.h>
#include <wallet/test/wallet_test_fixture.h>
@ -79,7 +80,7 @@ static void add_coin(CWallet& wallet, const CAmount& nValue, int nAge = 6*24, bo
tx.vout[nInput].nValue = nValue;
if (spendable) {
CTxDestination dest;
std::string error;
bilingual_str error;
const bool destination_ok = wallet.GetNewDestination(OutputType::BECH32, "", dest, error);
assert(destination_ok);
tx.vout[nInput].scriptPubKey = GetScriptForDestination(dest);

View file

@ -73,7 +73,7 @@ static CMutableTransaction TestSimpleSpend(const CTransaction& from, uint32_t in
keystore.AddKey(key);
std::map<COutPoint, Coin> coins;
coins[mtx.vin[0].prevout].out = from.vout[index];
std::map<int, std::string> input_errors;
std::map<int, bilingual_str> input_errors;
BOOST_CHECK(SignTransaction(mtx, &keystore, coins, SIGHASH_ALL, Params().HashGenesisBlock(), input_errors));
return mtx;
}
@ -593,7 +593,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
BOOST_CHECK(!wallet->TopUpKeyPool(1000));
CTxDestination dest;
std::string error;
bilingual_str error;
BOOST_CHECK(!wallet->GetNewDestination(OutputType::BECH32, "", dest, error));
}

View file

@ -1804,11 +1804,11 @@ bool CWallet::SignTransaction(CMutableTransaction& tx) const
const CWalletTx& wtx = mi->second;
coins[input.prevout] = Coin(wtx.tx->vout[input.prevout.n], wtx.m_confirm.block_height, wtx.IsCoinBase());
}
std::map<int, std::string> input_errors;
std::map<int, bilingual_str> input_errors;
return SignTransaction(tx, coins, SIGHASH_DEFAULT, input_errors);
}
bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const
{
// Try to sign with all ScriptPubKeyMans
tx.witness.vtxinwit.resize(tx.vin.size());
@ -2404,7 +2404,7 @@ bool CWallet::GetOnlinePakKey(CPubKey& online_pubkey, std::string& error)
}
/// end ELEMENTS
bool CWallet::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error, bool add_blinding_key)
bool CWallet::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, bilingual_str& error, bool add_blinding_key)
{
LOCK(cs_wallet);
error.clear();
@ -2418,7 +2418,7 @@ bool CWallet::GetNewDestination(const OutputType type, const std::string label,
std::visit(SetBlindingPubKeyVisitor(blinding_pubkey), dest);
}
} else {
error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type)).translated;
error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type));
}
if (result) {
SetAddressBook(dest, label, "receive");
@ -2427,7 +2427,7 @@ bool CWallet::GetNewDestination(const OutputType type, const std::string label,
return result;
}
bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& dest, std::string& error, bool add_blinding_key)
bool CWallet::GetNewChangeDestination(const OutputType type, CTxDestination& dest, bilingual_str& error, bool add_blinding_key)
{
LOCK(cs_wallet);
error.clear();
@ -2484,11 +2484,11 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co
return result;
}
bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal, std::string& error)
bool ReserveDestination::GetReservedDestination(CTxDestination& dest, bool internal, bilingual_str& error)
{
m_spk_man = pwallet->GetScriptPubKeyMan(type, internal);
if (!m_spk_man) {
error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type)).translated;
error = strprintf(_("Error: No %s addresses available."), FormatOutputType(type));
return false;
}
@ -3969,4 +3969,3 @@ bool CWallet::SetMasterBlindingKey(const uint256& key)
// END ELEMENTS
//

View file

@ -185,7 +185,7 @@ public:
}
//! Reserve an address
bool GetReservedDestination(CTxDestination& pubkey, bool internal, std::string& error);
bool GetReservedDestination(CTxDestination& pubkey, bool internal, bilingual_str& error);
//! Attach a blinding pubkey to a reserved address
void SetBlindingPubKey(const CPubKey& blinding_pubkey, CTxDestination& dest);
//! Return reserved address
@ -586,7 +586,7 @@ public:
/** Fetch the inputs and sign with SIGHASH_ALL. */
bool SignTransaction(CMutableTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/** Sign the tx given the input coins and sighash. */
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const;
bool SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, bilingual_str>& input_errors) const;
SigningResult SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const;
/**
@ -698,8 +698,8 @@ public:
void MarkDestinationsDirty(const std::set<CTxDestination>& destinations) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
bool GetOnlinePakKey(CPubKey& online_pubkey, std::string& error);
bool GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error, bool add_blinding_key = false);
bool GetNewChangeDestination(const OutputType type, CTxDestination& dest, std::string& error, bool add_blinding_key = false);
bool GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, bilingual_str& error, bool add_blinding_key = false);
bool GetNewChangeDestination(const OutputType type, CTxDestination& dest, bilingual_str& error, bool add_blinding_key = false);
isminetype IsMine(const CTxDestination& dest) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
isminetype IsMine(const CScript& script) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);