diff --git a/doc/developer-notes.md b/doc/developer-notes.md index a409a82a758c8..d48b8ec68a697 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -1186,6 +1186,11 @@ A few guidelines for introducing and reviewing new RPC interfaces: new RPC is replacing a deprecated RPC, to avoid both RPCs confusingly showing up in the command list. +- Use *invalid* Dash addresses (e.g. in the constant array `EXAMPLE_ADDRESS`) for + `RPCExamples` help documentation. + + - *Rationale*: Prevent accidental transactions by users. + - Use the `UNIX_EPOCH_TIME` constant when describing UNIX epoch time or timestamps in the documentation. diff --git a/doc/release-notes-17578.md b/doc/release-notes-17578.md index 1b07436bb14f1..664d17fd78dba 100644 --- a/doc/release-notes-17578.md +++ b/doc/release-notes-17578.md @@ -1,8 +1,13 @@ Deprecated or removed RPCs -------------------------- -- The `getaddressinfo` RPC `labels` field now returns an array of label name - strings. Previously, it returned an array of JSON objects containing `name` and - `purpose` key/value pairs, which is now deprecated and will be removed in - 0.21. To re-enable the previous behavior, launch bitcoind with - `-deprecatedrpc=labelspurpose`. +- RPC `getaddressinfo` changes: + + - the `label` field has been deprecated in favor of the `labels` field and + will be removed in 0.21. It can be re-enabled in the interim by launching + with `-deprecatedrpc=label`. + + - the `labels` behavior of returning an array of JSON objects containing name + and purpose key/value pairs has been deprecated in favor of an array of + label names and will be removed in 0.21. The previous behavior can be + re-enabled in the interim by launching with `-deprecatedrpc=labelspurpose`. diff --git a/src/psbt.cpp b/src/psbt.cpp index 529dbe7e3d879..0f204275e61bd 100644 --- a/src/psbt.cpp +++ b/src/psbt.cpp @@ -322,9 +322,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx) PSBTAnalysis result; bool calc_fee = true; - bool all_final = true; - bool only_missing_sigs = true; - bool only_missing_final = false; + CAmount in_amt = 0; result.inputs.resize(psbtx.tx->vin.size()); @@ -333,6 +331,9 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx) PSBTInput& input = psbtx.inputs[i]; PSBTInputAnalysis& input_analysis = result.inputs[i]; + // We set next role here and ratchet backwards as required + input_analysis.next = PSBTRole::EXTRACTOR; + // Check for a UTXO CTxOut utxo; if (psbtx.GetInputUTXO(utxo, i)) { @@ -361,7 +362,6 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx) // Check if it is final if (!utxo.IsNull() && !PSBTInputSigned(input)) { input_analysis.is_final = false; - all_final = false; // Figure out what is missing SignatureData outdata; @@ -377,11 +377,9 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx) if (outdata.missing_pubkeys.empty() && outdata.missing_redeem_script.IsNull() && !outdata.missing_sigs.empty()) { input_analysis.next = PSBTRole::SIGNER; } else { - only_missing_sigs = false; input_analysis.next = PSBTRole::UPDATER; } } else { - only_missing_final = true; input_analysis.next = PSBTRole::FINALIZER; } } else if (!utxo.IsNull()){ @@ -389,10 +387,14 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx) } } - if (all_final) { - only_missing_sigs = false; - result.next = PSBTRole::EXTRACTOR; + // Calculate next role for PSBT by grabbing "minumum" PSBTInput next role + result.next = PSBTRole::EXTRACTOR; + for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) { + PSBTInputAnalysis& input_analysis = result.inputs[i]; + result.next = std::min(result.next, input_analysis.next); } + assert(result.next > PSBTRole::CREATOR); + if (calc_fee) { // Get the output amount CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmount(0), @@ -441,17 +443,6 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx) result.estimated_feerate = feerate; } - if (only_missing_sigs) { - result.next = PSBTRole::SIGNER; - } else if (only_missing_final) { - result.next = PSBTRole::FINALIZER; - } else if (all_final) { - result.next = PSBTRole::EXTRACTOR; - } else { - result.next = PSBTRole::UPDATER; - } - } else { - result.next = PSBTRole::UPDATER; } return result; diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index c939745be4a36..98d64874df5f8 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -55,7 +55,7 @@ struct AddressTableEntryLessThan static AddressTableEntry::Type translateTransactionType(const QString &strPurpose, bool isMine) { AddressTableEntry::Type addressType = AddressTableEntry::Hidden; - // "refund" addresses aren't shown, and change addresses aren't in mapAddressBook at all. + // "refund" addresses aren't shown, and change addresses aren't returned by getAddresses at all. if (strPurpose == "send") addressType = AddressTableEntry::Sending; else if (strPurpose == "receive") diff --git a/src/qt/test/addressbooktests.cpp b/src/qt/test/addressbooktests.cpp index 3a7a93c4ac013..3d37f86138af1 100644 --- a/src/qt/test/addressbooktests.cpp +++ b/src/qt/test/addressbooktests.cpp @@ -98,7 +98,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node) auto check_addbook_size = [wallet](int expected_size) { LOCK(wallet->cs_wallet); - QCOMPARE(static_cast(wallet->mapAddressBook.size()), expected_size); + QCOMPARE(static_cast(wallet->m_address_book.size()), expected_size); }; // We should start with the two addresses we added earlier and nothing else. diff --git a/src/rpc/evo.cpp b/src/rpc/evo.cpp index fa317e348601f..3e48b690214c3 100644 --- a/src/rpc/evo.cpp +++ b/src/rpc/evo.cpp @@ -354,7 +354,7 @@ static void protx_register_fund_help(const JSONRPCRequest& request, bool legacy) std::string rpc_name = legacy ? "register_fund_legacy" : "register_fund"; std::string rpc_full_name = std::string("protx ").append(rpc_name); std::string pubkey_operator = legacy ? "\"0532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\"" : "\"8532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\""; - std::string rpc_example = rpc_name.append(" \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" ").append(pubkey_operator).append(" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\""); + std::string rpc_example = rpc_name.append(" \"" + EXAMPLE_ADDRESS[0] + "\" \"1.2.3.4:1234\" \"" + EXAMPLE_ADDRESS[1] + "\" ").append(pubkey_operator).append(" \"" + EXAMPLE_ADDRESS[1] + "\" 0 \"" + EXAMPLE_ADDRESS[0] + "\""); RPCHelpMan{rpc_full_name, "\nCreates, funds and sends a ProTx to the network. The resulting transaction will move 1000 Dash\n" "to the address specified by collateralAddress and will then function as the collateral of your\n" @@ -390,7 +390,7 @@ static void protx_register_help(const JSONRPCRequest& request, bool legacy) std::string rpc_name = legacy ? "register_legacy" : "register"; std::string rpc_full_name = std::string("protx ").append(rpc_name); std::string pubkey_operator = legacy ? "\"0532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\"" : "\"8532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\""; - std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" ").append(pubkey_operator).append(" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\""); + std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"" + EXAMPLE_ADDRESS[1] + "\" ").append(pubkey_operator).append(" \"" + EXAMPLE_ADDRESS[1] + "\" 0 \"" + EXAMPLE_ADDRESS[0] + "\""); RPCHelpMan{rpc_full_name, "\nSame as \"protx register_fund\", but with an externally referenced collateral.\n" "The collateral is specified through \"collateralHash\" and \"collateralIndex\" and must be an unspent\n" @@ -425,7 +425,7 @@ static void protx_register_prepare_help(const JSONRPCRequest& request, bool lega std::string rpc_name = legacy ? "register_prepare_legacy" : "register_prepare"; std::string rpc_full_name = std::string("protx ").append(rpc_name); std::string pubkey_operator = legacy ? "\"0532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\"" : "\"8532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\""; - std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" ").append(pubkey_operator).append(" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\""); + std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"" + EXAMPLE_ADDRESS[1] + "\" ").append(pubkey_operator).append(" \"" + EXAMPLE_ADDRESS[1] + "\" 0 \"" + EXAMPLE_ADDRESS[0] + "\""); RPCHelpMan{rpc_full_name, "\nCreates an unsigned ProTx and a message that must be signed externally\n" "with the private key that corresponds to collateralAddress to prove collateral ownership.\n" @@ -505,7 +505,7 @@ static void protx_register_fund_hpmn_help(const JSONRPCRequest& request) RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"}, }, RPCExamples{ - HelpExampleCli("protx", "register_fund_hpmn \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" 1000 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")}, + HelpExampleCli("protx", "register_fund_hpmn \"" + EXAMPLE_ADDRESS[0] + "\" 1000 \"1.2.3.4:1234\" \"" + EXAMPLE_ADDRESS[1] + "\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"" + EXAMPLE_ADDRESS[1] + "\" 0 \"" + EXAMPLE_ADDRESS[0] + "\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")}, }.Check(request); } @@ -539,7 +539,7 @@ static void protx_register_hpmn_help(const JSONRPCRequest& request) RPCResult::Type::STR_HEX, "hex", "The serialized signed ProTx in hex format"}, }, RPCExamples{ - HelpExampleCli("protx", "register_hpmn \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")}, + HelpExampleCli("protx", "register_hpmn \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"" + EXAMPLE_ADDRESS[1] + "\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"" + EXAMPLE_ADDRESS[1] + "\" 0 \"" + EXAMPLE_ADDRESS[0] + "\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")}, }.Check(request); } @@ -570,7 +570,7 @@ static void protx_register_prepare_hpmn_help(const JSONRPCRequest& request) {RPCResult::Type::STR_HEX, "collateralAddress", "The collateral address"}, {RPCResult::Type::STR_HEX, "signMessage", "The string message that needs to be signed with the collateral key"}, }}, - RPCExamples{HelpExampleCli("protx", "register_prepare_hpmn \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\" 0 \"XrVhS9LogauRJGJu2sHuryjhpuex4RNPSb\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")}, + RPCExamples{HelpExampleCli("protx", "register_prepare_hpmn \"0123456701234567012345670123456701234567012345670123456701234567\" 0 \"1.2.3.4:1234\" \"" + EXAMPLE_ADDRESS[1] + "\" \"93746e8731c57f87f79b3620a7982924e2931717d49540a85864bd543de11c43fb868fd63e501a1db37e19ed59ae6db4\" \"" + EXAMPLE_ADDRESS[1] + "\" 0 \"" + EXAMPLE_ADDRESS[0] + "\" \"f2dbd9b0a1f541a7c44d34a58674d0262f5feca5\" 22821 22822")}, }.Check(request); } @@ -997,7 +997,7 @@ static void protx_update_registrar_help(const JSONRPCRequest& request, bool lega std::string rpc_name = legacy ? "update_registrar_legacy" : "update_registrar"; std::string rpc_full_name = std::string("protx ").append(rpc_name); std::string pubkey_operator = legacy ? "\"0532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\"" : "\"8532646990082f4fd639f90387b1551f2c7c39d37392cb9055a06a7e85c1d23692db8f87f827886310bccc1e29db9aee\""; - std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" ").append(pubkey_operator).append(" \"Xt9AMWaYSz7tR7Uo7gzXA3m4QmeWgrR3rr\""); + std::string rpc_example = rpc_name.append(" \"0123456701234567012345670123456701234567012345670123456701234567\" ").append(pubkey_operator).append(" \"" + EXAMPLE_ADDRESS[1] + "\""); RPCHelpMan{rpc_full_name, "\nCreates and sends a ProUpRegTx to the network. This will update the operator key, voting key and payout\n" "address of the masternode specified by \"proTxHash\".\n" diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index 8ff8033519868..993368f7a9ac2 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -227,8 +227,8 @@ static UniValue validateaddress(const JSONRPCRequest& request) } }, RPCExamples{ - HelpExampleCli("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") + - HelpExampleRpc("validateaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"") + HelpExampleCli("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") + + HelpExampleRpc("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") }, }.Check(request); @@ -444,11 +444,11 @@ static UniValue verifymessage(const JSONRPCRequest& request) "\nUnlock the wallet for 30 seconds\n" + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + "\nCreate the signature\n" - + HelpExampleCli("signmessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"my message\"") + + + HelpExampleCli("signmessage", "\"" + EXAMPLE_ADDRESS[0] + "\" \"my message\"") + "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"signature\" \"my message\"") + + + HelpExampleCli("verifymessage", "\"" + EXAMPLE_ADDRESS[0] + "\" \"signature\" \"my message\"") + "\nAs a JSON-RPC call\n" - + HelpExampleRpc("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", \"signature\", \"my message\"") + + HelpExampleRpc("verifymessage", "\"" + EXAMPLE_ADDRESS[0] + "\", \"signature\", \"my message\"") }, }.Check(request); @@ -490,7 +490,7 @@ static UniValue signmessagewithprivkey(const JSONRPCRequest& request) "\nCreate the signature\n" + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") + "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"signature\" \"my message\"") + + + HelpExampleCli("verifymessage", "\"" + EXAMPLE_ADDRESS[0] + "\" \"signature\" \"my message\"") + "\nAs a JSON-RPC call\n" + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"") }, @@ -684,8 +684,8 @@ static UniValue getaddressmempool(const JSONRPCRequest& request) }}, }}, RPCExamples{ - HelpExampleCli("getaddressmempool", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + HelpExampleCli("getaddressmempool", "'{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}'") + + HelpExampleRpc("getaddressmempool", "{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}") }, }.Check(request); @@ -755,8 +755,8 @@ static UniValue getaddressutxos(const JSONRPCRequest& request) }}, }}, RPCExamples{ - HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + HelpExampleCli("getaddressutxos", "'{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}'") + + HelpExampleRpc("getaddressutxos", "{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}") }, }.Check(request); @@ -822,8 +822,8 @@ static UniValue getaddressdeltas(const JSONRPCRequest& request) }}, }}, RPCExamples{ - HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + HelpExampleCli("getaddressdeltas", "'{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}'") + + HelpExampleRpc("getaddressdeltas", "{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}") }, }.Check(request); @@ -903,8 +903,8 @@ static UniValue getaddressbalance(const JSONRPCRequest& request) {RPCResult::Type::NUM, "received", "The total number of duffs received (including change)"}, }}, RPCExamples{ - HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + HelpExampleCli("getaddressbalance", "'{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}'") + + HelpExampleRpc("getaddressbalance", "{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}") }, }.Check(request); @@ -967,8 +967,8 @@ static UniValue getaddresstxids(const JSONRPCRequest& request) {{RPCResult::Type::STR_HEX, "transactionid", "The transaction id"}} }, RPCExamples{ - HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}'") - + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\"]}") + HelpExampleCli("getaddresstxids", "'{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}'") + + HelpExampleRpc("getaddresstxids", "{\"addresses\": [\"" + EXAMPLE_ADDRESS[0] + "\"]}") }, }.Check(request); diff --git a/src/rpc/util.cpp b/src/rpc/util.cpp index e1803542405c4..726360ed46f61 100644 --- a/src/rpc/util.cpp +++ b/src/rpc/util.cpp @@ -18,7 +18,7 @@ #include const std::string UNIX_EPOCH_TIME = "UNIX epoch time"; - +const std::string EXAMPLE_ADDRESS[2] = {"XunLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPw0", "XwQQkwA4FYkq2XERzMY2CiAZhJTEDAbtc0"}; void RPCTypeCheck(const UniValue& params, const std::list& typesExpected, diff --git a/src/rpc/util.h b/src/rpc/util.h index 2b07a623d2d01..2ef09eea2ccf1 100644 --- a/src/rpc/util.h +++ b/src/rpc/util.h @@ -29,6 +29,12 @@ */ extern const std::string UNIX_EPOCH_TIME; +/** + * Example Dash addresses for the RPCExamples help documentation. They are intentionally + * invalid to prevent accidental transactions by users. + */ +extern const std::string EXAMPLE_ADDRESS[2]; + class FillableSigningProvider; class FillableSigningProvider; class CPubKey; diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index b2863d5e93109..213a66542d0d7 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -265,6 +266,10 @@ FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, { BlockTransactionsRequest btr; DeserializeFromFuzzingInput(buffer, btr); }) +FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, { + SnapshotMetadata snapshot_metadata; + DeserializeFromFuzzingInput(buffer, snapshot_metadata); +}) FUZZ_TARGET_DESERIALIZE(uint160_deserialize, { uint160 u160; DeserializeFromFuzzingInput(buffer, u160); diff --git a/src/test/fuzz/psbt.cpp b/src/test/fuzz/psbt.cpp index 0abdb4178e646..09760d1fce089 100644 --- a/src/test/fuzz/psbt.cpp +++ b/src/test/fuzz/psbt.cpp @@ -17,7 +17,7 @@ void initialize_psbt() { - static const auto verify_handle = std::make_unique(); + static const ECCVerifyHandle verify_handle; } FUZZ_TARGET_INIT(psbt, initialize_psbt) diff --git a/src/test/fuzz/script.cpp b/src/test/fuzz/script.cpp index fee9583b06bf9..8a6c5added219 100644 --- a/src/test/fuzz/script.cpp +++ b/src/test/fuzz/script.cpp @@ -46,10 +46,12 @@ FUZZ_TARGET_INIT(script, initialize_script) CompressedScript compressed; if (CompressScript(script, compressed)) { const unsigned int size = compressed[0]; + compressed.erase(compressed.begin()); assert(size <= 5); CScript decompressed_script; const bool ok = DecompressScript(decompressed_script, size, compressed); assert(ok); + assert(script == decompressed_script); } CTxDestination address; diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index d8afe15771074..200bf3e8316c2 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -240,8 +240,8 @@ class WalletImpl : public Wallet std::string* purpose) override { LOCK(m_wallet->cs_wallet); - auto it = m_wallet->mapAddressBook.find(dest); - if (it == m_wallet->mapAddressBook.end()) { + auto it = m_wallet->m_address_book.find(dest); + if (it == m_wallet->m_address_book.end() || it->second.IsChange()) { return false; } if (name) { @@ -259,7 +259,8 @@ class WalletImpl : public Wallet { LOCK(m_wallet->cs_wallet); std::vector result; - for (const auto& item : m_wallet->mapAddressBook) { + for (const auto& item : m_wallet->m_address_book) { + if (item.second.IsChange()) continue; result.emplace_back(item.first, m_wallet->IsMine(item.first), item.second.name, item.second.purpose); } return result; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index e460beded9d4b..416f24fb94c8a 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -142,7 +142,7 @@ UniValue importprivkey(const JSONRPCRequest& request) { pwallet->MarkDirty(); - if (!request.params[1].isNull() || pwallet->mapAddressBook.count(vchAddress) == 0) { + if (!request.params[1].isNull() || !pwallet->FindAddressBookEntry(vchAddress)) { pwallet->SetAddressBook(vchAddress, strLabel, "receive"); } @@ -1011,8 +1011,9 @@ UniValue dumpwallet(const JSONRPCRequest& request) CKey key; if (spk_man.GetKey(keyid, key)) { file << strprintf("%s %s ", EncodeSecret(key), strTime); - if (pwallet->mapAddressBook.count(pkhash)) { - file << strprintf("label=%s", EncodeDumpString(pwallet->mapAddressBook.at(pkhash).name)); + const auto* address_book_entry = pwallet->FindAddressBookEntry(pkhash); + if (address_book_entry) { + file << strprintf("label=%s", EncodeDumpString(address_book_entry->name)); } else if (mapKeyPool.count(keyid)) { file << "reserve=1"; } else { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index bf4983c6ed489..d9e79b1e08d2b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -287,8 +287,8 @@ static UniValue setlabel(const JSONRPCRequest& request) }, RPCResult{RPCResult::Type::NONE, "", ""}, RPCExamples{ - HelpExampleCli("setlabel", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"tabby\"") - + HelpExampleRpc("setlabel", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", \"tabby\"") + HelpExampleCli("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\" \"tabby\"") + + HelpExampleRpc("setlabel", "\"" + EXAMPLE_ADDRESS[0] + "\", \"tabby\"") }, }.Check(request); @@ -383,10 +383,10 @@ static UniValue sendtoaddress(const JSONRPCRequest& request) RPCResult::Type::STR_HEX, "txid", "The transaction id." }, RPCExamples{ - HelpExampleCli("sendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1") - + HelpExampleCli("sendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1 \"donation\" \"seans outpost\"") - + HelpExampleCli("sendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0.1 \"\" \"\" true") - + HelpExampleRpc("sendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", 0.1, \"donation\", \"seans outpost\"") + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1") + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"donation\" \"seans outpost\"") + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0.1 \"\" \"\" true") + + HelpExampleRpc("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 0.1, \"donation\", \"seans outpost\"") }, }.Check(request); @@ -500,8 +500,9 @@ static UniValue listaddressgroupings(const JSONRPCRequest& request) addressInfo.push_back(EncodeDestination(address)); addressInfo.push_back(ValueFromAmount(balances[address])); { - if (pwallet->mapAddressBook.find(address) != pwallet->mapAddressBook.end()) { - addressInfo.push_back(pwallet->mapAddressBook.find(address)->second.name); + const auto* address_book_entry = pwallet->FindAddressBookEntry(address); + if (address_book_entry) { + addressInfo.push_back(address_book_entry->name); } } jsonGrouping.push_back(addressInfo); @@ -570,11 +571,11 @@ static UniValue signmessage(const JSONRPCRequest& request) "\nUnlock the wallet for 30 seconds\n" + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") + "\nCreate the signature\n" - + HelpExampleCli("signmessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"my message\"") + + + HelpExampleCli("signmessage", "\"" + EXAMPLE_ADDRESS[0] + "\" \"my message\"") + "\nVerify the signature\n" - + HelpExampleCli("verifymessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" \"signature\" \"my message\"") + + + HelpExampleCli("verifymessage", "\"" + EXAMPLE_ADDRESS[0] + "\" \"signature\" \"my message\"") + "\nAs a JSON-RPC call\n" - + HelpExampleRpc("signmessage", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", \"my message\"") + + HelpExampleRpc("signmessage", "\"" + EXAMPLE_ADDRESS[0] + "\", \"my message\"") }, }.Check(request); @@ -624,13 +625,13 @@ static UniValue getreceivedbyaddress(const JSONRPCRequest& request) }, RPCExamples{ "\nThe amount from transactions with at least 1 confirmation\n" - + HelpExampleCli("getreceivedbyaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\"") + + + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") + "\nThe amount including unconfirmed transactions, zero confirmations\n" - + HelpExampleCli("getreceivedbyaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 0") + + + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 0") + "\nThe amount with at least 6 confirmations\n" - + HelpExampleCli("getreceivedbyaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 6") + + + HelpExampleCli("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 6") + "\nAs a JSON-RPC call\n" - + HelpExampleRpc("getreceivedbyaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\", 6") + + HelpExampleRpc("getreceivedbyaddress", "\"" + EXAMPLE_ADDRESS[0] + "\", 6") }, }.Check(request); @@ -863,11 +864,11 @@ static UniValue sendmany(const JSONRPCRequest& request) }, RPCExamples{ "\nSend two amounts to two different addresses:\n" - + HelpExampleCli("sendmany", "\"\" \"{\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\\\":0.01,\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcG\\\":0.02}\"") + + + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\"") + "\nSend two amounts to two different addresses setting the confirmation and comment:\n" - + HelpExampleCli("sendmany", "\"\" \"{\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\\\":0.01,\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcG\\\":0.02}\" 6 false \"testing\"") + + + HelpExampleCli("sendmany", "\"\" \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\" 6 false \"testing\"") + "\nAs a json rpc call\n" - + HelpExampleRpc("sendmany", "\"\", \"{\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\\\":0.01,\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcG\\\":0.02}\", 6, false, \"testing\"") + + HelpExampleRpc("sendmany", "\"\", \"{\\\"" + EXAMPLE_ADDRESS[0] + "\\\":0.01,\\\"" + EXAMPLE_ADDRESS[1] + "\\\":0.02}\", 6, false, \"testing\"") }, }.Check(request); @@ -987,9 +988,9 @@ UniValue addmultisigaddress(const JSONRPCRequest& request) }, RPCExamples{ "\nAdd a multisig address from 2 addresses\n" - + HelpExampleCli("addmultisigaddress", "2 \"[\\\"Xt4qk9uKvQYAonVGSZNXqxeDmtjaEWgfrS\\\",\\\"XoSoWQkpgLpppPoyyzbUFh1fq2RBvW6UK2\\\"]\"") + + + HelpExampleCli("addmultisigaddress", "2 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") + "\nAs a JSON-RPC call\n" - + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"Xt4qk9uKvQYAonVGSZNXqxeDmtjaEWgfrS\\\",\\\"XoSoWQkpgLpppPoyyzbUFh1fq2RBvW6UK2\\\"]\"") + + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") }, }.Check(request); @@ -1114,13 +1115,13 @@ static UniValue ListReceived(const CWallet * const pwallet, const UniValue& para UniValue ret(UniValue::VARR); std::map label_tally; - // Create mapAddressBook iterator + // Create m_address_book iterator // If we aren't filtering, go from begin() to end() - auto start = pwallet->mapAddressBook.begin(); - auto end = pwallet->mapAddressBook.end(); + auto start = pwallet->m_address_book.begin(); + auto end = pwallet->m_address_book.end(); // If we are filtering, find() the applicable entry if (has_filtered_address) { - start = pwallet->mapAddressBook.find(filtered_address); + start = pwallet->m_address_book.find(filtered_address); if (start != end) { end = std::next(start); } @@ -1128,6 +1129,7 @@ static UniValue ListReceived(const CWallet * const pwallet, const UniValue& para for (auto item_it = start; item_it != end; ++item_it) { + if (item_it->second.IsChange()) continue; const CTxDestination& address = item_it->first; const std::string& label = item_it->second.name; auto it = mapTally.find(address); @@ -1230,7 +1232,7 @@ static UniValue listreceivedbyaddress(const JSONRPCRequest& request) HelpExampleCli("listreceivedbyaddress", "") + HelpExampleCli("listreceivedbyaddress", "6 false true") + HelpExampleRpc("listreceivedbyaddress", "6, false, true, true") - + HelpExampleRpc("listreceivedbyaddress", "6, false, true, true, \"XbtdLrTsrPDhGy1wXtwKYoBpuKovE3JeBK\"") + + HelpExampleRpc("listreceivedbyaddress", "6, false, true, true, \"" + EXAMPLE_ADDRESS[0] + "\"") }, }.Check(request); @@ -1330,8 +1332,9 @@ static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx, std::map::const_iterator it = wtx.mapValue.find("DS"); entry.pushKV("category", (it != wtx.mapValue.end() && it->second == "1") ? "coinjoin" : "send"); entry.pushKV("amount", ValueFromAmount(-s.amount)); - if (pwallet->mapAddressBook.count(s.destination)) { - entry.pushKV("label", pwallet->mapAddressBook.at(s.destination).name); + const auto* address_book_entry = pwallet->FindAddressBookEntry(s.destination); + if (address_book_entry) { + entry.pushKV("label", address_book_entry->name); } entry.pushKV("vout", s.vout); entry.pushKV("fee", ValueFromAmount(-nFee)); @@ -1348,8 +1351,9 @@ static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx, for (const COutputEntry& r : listReceived) { std::string label; - if (pwallet->mapAddressBook.count(r.destination)) { - label = pwallet->mapAddressBook.at(r.destination).name; + const auto* address_book_entry = pwallet->FindAddressBookEntry(r.destination); + if (address_book_entry) { + label = address_book_entry->name; } if (filter_label && label != *filter_label) { continue; @@ -1373,7 +1377,7 @@ static void ListTransactions(const CWallet* const pwallet, const CWalletTx& wtx, entry.pushKV("category", "receive"); } entry.pushKV("amount", ValueFromAmount(r.amount)); - if (pwallet->mapAddressBook.count(r.destination)) { + if (address_book_entry) { entry.pushKV("label", label); } entry.pushKV("vout", r.vout); @@ -1555,7 +1559,6 @@ static UniValue listsinceblock(const JSONRPCRequest& request) TransactionDescriptionString()), { {RPCResult::Type::BOOL, "abandoned", "'true' if the transaction has been abandoned (inputs are respendable). Only available for the 'send' category of transactions."}, - {RPCResult::Type::STR, "comment", "If a comment is associated with the transaction."}, {RPCResult::Type::STR, "label", "A comment for the address/transaction, if any."}, {RPCResult::Type::STR, "to", "If a comment to is associated with the transaction."}, })}, @@ -2034,7 +2037,7 @@ static UniValue walletlock(const JSONRPCRequest& request) "\nSet the passphrase for 2 minutes to perform a transaction\n" + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") + "\nPerform a send (requires passphrase set)\n" - + HelpExampleCli("sendtoaddress", "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwG\" 1.0") + + + HelpExampleCli("sendtoaddress", "\"" + EXAMPLE_ADDRESS[0] + "\" 1.0") + "\nClear the passphrase since we are done before 2 minutes is up\n" + HelpExampleCli("walletlock", "") + "\nAs a JSON-RPC call\n" @@ -3029,8 +3032,8 @@ static UniValue listunspent(const JSONRPCRequest& request) }}, RPCExamples{ HelpExampleCli("listunspent", "") - + HelpExampleCli("listunspent", "6 9999999 \"[\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\\\",\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcg\\\"]\"") - + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\\\",\\\"XuQQkwA4FYkq2XERzMY2CiAZhJTEDAbtcg\\\"]\"") + + HelpExampleCli("listunspent", "6 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") + + HelpExampleRpc("listunspent", "6, 9999999 \"[\\\"" + EXAMPLE_ADDRESS[0] + "\\\",\\\"" + EXAMPLE_ADDRESS[1] + "\\\"]\"") + HelpExampleCli("listunspent", "6 9999999 '[]' true '{ \"minimumAmount\": 0.005 }'") + HelpExampleRpc("listunspent", "6, 9999999, [] , true, { \"minimumAmount\": 0.005 } ") }, @@ -3153,9 +3156,9 @@ static UniValue listunspent(const JSONRPCRequest& request) if (fValidAddress) { entry.pushKV("address", EncodeDestination(address)); - auto i = pwallet->mapAddressBook.find(address); - if (i != pwallet->mapAddressBook.end()) { - entry.pushKV("label", i->second.name); + const auto* address_book_entry = pwallet->FindAddressBookEntry(address); + if (address_book_entry) { + entry.pushKV("label", address_book_entry->name); } std::unique_ptr provider = pwallet->GetSolvingProvider(scriptPubKey); @@ -3622,8 +3625,6 @@ static UniValue AddressBookDataToJSON(const CAddressBookData& data, const bool v UniValue getaddressinfo(const JSONRPCRequest& request) { - const std::string example_address = "\"XwnLY9Tf7Zsef8gMGL2fhWA9ZmMjt4KPwg\""; - RPCHelpMan{"getaddressinfo", "\nReturn information about the given dash address.\n" "Some of the information will only be present if the address is in the active wallet.\n", @@ -3654,7 +3655,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request) {RPCResult::Type::NUM, "sigsrequired", /* optional */ true, "The number of signatures required to spend multisig output (only if script is multisig)."}, {RPCResult::Type::STR_HEX, "pubkey", /* optional */ true, "The hex value of the raw public key, for single-key addresses."}, {RPCResult::Type::BOOL, "iscompressed", /* optional */ true, "If the pubkey is compressed."}, - {RPCResult::Type::STR, "label", "The label associated with the address. Defaults to \"\". Equivalent to the name label in the labels array below."}, + {RPCResult::Type::STR, "label", "DEPRECATED. The label associated with the address. Defaults to \"\". Replaced by the labels array below."}, {RPCResult::Type::NUM_TIME, "timestamp", /* optional */ true, "The creation time of the key, if available, expressed in " + UNIX_EPOCH_TIME + "."}, {RPCResult::Type::STR_HEX, "hdchainid", /* optional */ true, "The ID of the HD chain."}, {RPCResult::Type::STR, "hdkeypath", /* optional */ true, "The HD keypath, if the key is HD and available."}, @@ -3662,18 +3663,18 @@ UniValue getaddressinfo(const JSONRPCRequest& request) {RPCResult::Type::STR_HEX, "hdmasterfingerprint", /* optional */ true, "The fingerprint of the master key."}, {RPCResult::Type::ARR, "labels", "An array of labels associated with the address. Currently limited to one label but returned as an array to keep the API stable if multiple labels are enabled in the future.", { - {RPCResult::Type::STR, "label name", "The label name. Defaults to \"\". Equivalent to the label field above."}, + {RPCResult::Type::STR, "label name", "The label name. Defaults to \"\"."}, {RPCResult::Type::OBJ, "", "json object of label data", { - {RPCResult::Type::STR, "name", "The label name. Defaults to \"\". Equivalent to the label field above."}, + {RPCResult::Type::STR, "name", "The label name. Defaults to \"\"."}, {RPCResult::Type::STR, "purpose", "The Purpose of the associated address (send or receive)."}, }}, }}, } }, RPCExamples{ - HelpExampleCli("getaddressinfo", example_address) - + HelpExampleRpc("getaddressinfo", example_address) + HelpExampleCli("getaddressinfo", EXAMPLE_ADDRESS[0]) + + HelpExampleRpc("getaddressinfo", EXAMPLE_ADDRESS[0]) }, }.Check(request); @@ -3713,11 +3714,12 @@ UniValue getaddressinfo(const JSONRPCRequest& request) UniValue detail = DescribeWalletAddress(pwallet, dest); ret.pushKVs(detail); - // Return label field if existing. Currently only one label can be - // associated with an address, so the label should be equivalent to the + // DEPRECATED: Return label field if existing. Currently only one label can + // be associated with an address, so the label should be equivalent to the // value of the name key/value pair in the labels array below. - if (pwallet->mapAddressBook.count(dest)) { - ret.pushKV("label", pwallet->mapAddressBook.at(dest).name); + const auto* address_book_entry = pwallet->FindAddressBookEntry(dest); + if (pwallet->chain().rpcEnableDeprecated("label") && address_book_entry) { + ret.pushKV("label", address_book_entry->name); } ret.pushKV("ischange", pwallet->IsChange(scriptPubKey)); @@ -3746,16 +3748,14 @@ UniValue getaddressinfo(const JSONRPCRequest& request) // associated with an address, but we return an array so the API remains // stable if we allow multiple labels to be associated with an address in // the future. - // - // DEPRECATED: The previous behavior of returning an array containing a JSON - // object of `name` and `purpose` key/value pairs has been deprecated. UniValue labels(UniValue::VARR); - std::map::const_iterator mi = pwallet->mapAddressBook.find(dest); - if (mi != pwallet->mapAddressBook.end()) { + if (address_book_entry) { + // DEPRECATED: The previous behavior of returning an array containing a + // JSON object of `name` and `purpose` key/value pairs is deprecated. if (pwallet->chain().rpcEnableDeprecated("labelspurpose")) { - labels.push_back(AddressBookDataToJSON(mi->second, true)); + labels.push_back(AddressBookDataToJSON(*address_book_entry, true)); } else { - labels.push_back(mi->second.name); + labels.push_back(address_book_entry->name); } } ret.pushKV("labels", std::move(labels)); @@ -3796,10 +3796,11 @@ static UniValue getaddressesbylabel(const JSONRPCRequest& request) // Find all addresses that have the given label UniValue ret(UniValue::VOBJ); std::set addresses; - for (const std::pair item : pwallet->mapAddressBook) { + for (const std::pair& item : pwallet->m_address_book) { + if (item.second.IsChange()) continue; if (item.second.name == label) { std::string address = EncodeDestination(item.first); - // CWallet::mapAddressBook is not expected to contain duplicate + // CWallet::m_address_book is not expected to contain duplicate // address strings, but build a separate set as a precaution just in // case it does. bool unique = addresses.emplace(address).second; @@ -3857,7 +3858,8 @@ static UniValue listlabels(const JSONRPCRequest& request) // Add to a set to sort by label name, then insert into Univalue array std::set label_set; - for (const std::pair entry : pwallet->mapAddressBook) { + for (const std::pair& entry : pwallet->m_address_book) { + if (entry.second.IsChange()) continue; if (purpose.empty() || entry.second.purpose == purpose) { label_set.insert(entry.second.name); } diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index cc651562c88e0..ff93c8c4c1aba 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -310,10 +310,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) // Verify getaddressinfo RPC produces more or less expected results BOOST_FIXTURE_TEST_CASE(rpc_getaddressinfo, TestChain100Setup) { - NodeContext node; - auto chain = interfaces::MakeChain(node); - - std::shared_ptr wallet = std::make_shared(chain.get(), "", CreateMockWalletDatabase()); + std::shared_ptr wallet = std::make_shared(m_node.chain.get(), "", CreateMockWalletDatabase()); wallet->SetupLegacyScriptPubKeyMan(); AddWallet(wallet); CoreContext context{m_node}; @@ -369,12 +366,15 @@ BOOST_FIXTURE_TEST_CASE(rpc_getaddressinfo, TestChain100Setup) BOOST_CHECK_EQUAL(find_value(response, "iswatchonly").get_bool(), false); BOOST_CHECK_EQUAL(find_value(response, "isscript").get_bool(), true); BOOST_CHECK_EQUAL(find_value(response, "ischange").get_bool(), false); - BOOST_CHECK_EQUAL(find_value(response, "label").get_str(), ""); BOOST_CHECK_EQUAL(find_value(response, "sigsrequired").get_int(), 2); + BOOST_CHECK(find_value(response, "label").isNull()); + UniValue labels = find_value(response, "labels").get_array(); UniValue pubkeys = find_value(response, "pubkeys").get_array(); UniValue addresses = find_value(response, "addresses").get_array(); + BOOST_CHECK_EQUAL(labels.size(), 1); + BOOST_CHECK_EQUAL(labels[0].get_str(), ""); BOOST_CHECK_EQUAL(addresses.size(), 2); BOOST_CHECK_EQUAL(addresses[0].get_str(), addr1); BOOST_CHECK_EQUAL(addresses[1].get_str(), addr2); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d4b38cce82a17..668488ae99249 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1501,8 +1501,9 @@ bool CWallet::IsChange(const CScript& script) const return true; LOCK(cs_wallet); - if (!mapAddressBook.count(address)) + if (!FindAddressBookEntry(address)) { return true; + } } return false; } @@ -3905,11 +3906,11 @@ bool CWallet::SetAddressBookWithDB(WalletBatch& batch, const CTxDestination& add bool fUpdated = false; { LOCK(cs_wallet); - std::map::iterator mi = mapAddressBook.find(address); - fUpdated = mi != mapAddressBook.end(); - mapAddressBook[address].name = strName; + std::map::iterator mi = m_address_book.find(address); + fUpdated = (mi != m_address_book.end() && !mi->second.IsChange()); + m_address_book[address].SetLabel(strName); if (!strPurpose.empty()) /* update purpose only if requested */ - mapAddressBook[address].purpose = strPurpose; + m_address_book[address].purpose = strPurpose; } NotifyAddressBookChanged(this, address, strName, IsMine(address) != ISMINE_NO, strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) ); @@ -3926,16 +3927,21 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const std::string& s bool CWallet::DelAddressBook(const CTxDestination& address) { + // If we want to delete receiving addresses, we need to take care that DestData "used" (and possibly newer DestData) gets preserved (and the "deleted" address transformed into a change entry instead of actually being deleted) + // NOTE: This isn't a problem for sending addresses because they never have any DestData yet! + // When adding new DestData, it should be considered here whether to retain or delete it (or move it?). + assert(!IsMine(address)); + { LOCK(cs_wallet); // Delete destdata tuples associated with address std::string strAddress = EncodeDestination(address); - for (const std::pair &item : mapAddressBook[address].destdata) + for (const std::pair &item : m_address_book[address].destdata) { WalletBatch(*database).EraseDestData(strAddress, item.first); } - mapAddressBook.erase(address); + m_address_book.erase(address); } NotifyAddressBookChanged(this, address, "", IsMine(address) != ISMINE_NO, "", CT_DELETED); @@ -4172,8 +4178,9 @@ std::set CWallet::GetLabelAddresses(const std::string& label) co { LOCK(cs_wallet); std::set result; - for (const std::pair& item : mapAddressBook) + for (const std::pair& item : m_address_book) { + if (item.second.IsChange()) continue; const CTxDestination& address = item.first; const std::string& strName = item.second.name; if (strName == label) @@ -4406,26 +4413,26 @@ bool CWallet::AddDestData(WalletBatch& batch, const CTxDestination &dest, const if (std::get_if(&dest)) return false; - mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); + m_address_book[dest].destdata.insert(std::make_pair(key, value)); return batch.WriteDestData(EncodeDestination(dest), key, value); } bool CWallet::EraseDestData(WalletBatch& batch, const CTxDestination &dest, const std::string &key) { - if (!mapAddressBook[dest].destdata.erase(key)) + if (!m_address_book[dest].destdata.erase(key)) return false; return batch.EraseDestData(EncodeDestination(dest), key); } void CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value) { - mapAddressBook[dest].destdata.insert(std::make_pair(key, value)); + m_address_book[dest].destdata.insert(std::make_pair(key, value)); } bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const { - std::map::const_iterator i = mapAddressBook.find(dest); - if(i != mapAddressBook.end()) + std::map::const_iterator i = m_address_book.find(dest); + if(i != m_address_book.end()) { CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key); if(j != i->second.destdata.end()) @@ -4441,7 +4448,7 @@ bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, st std::vector CWallet::GetDestValues(const std::string& prefix) const { std::vector values; - for (const auto& address : mapAddressBook) { + for (const auto& address : m_address_book) { for (const auto& data : address.second.destdata) { if (!data.first.compare(0, prefix.size(), prefix)) { values.emplace_back(data.second); @@ -4801,7 +4808,7 @@ std::shared_ptr CWallet::Create(interfaces::Chain& chain, const std::st walletInstance->WalletLogPrintf("setExternalKeyPool.size() = %u\n", walletInstance->KeypoolCountExternalKeys()); walletInstance->WalletLogPrintf("setInternalKeyPool.size() = %u\n", walletInstance->KeypoolCountInternalKeys()); walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size()); - walletInstance->WalletLogPrintf("mapAddressBook.size() = %u\n", walletInstance->mapAddressBook.size()); + walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size()); for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) { walletInstance->WalletLogPrintf("nTimeFirstKey = %u\n", spk_man->GetTimeFirstKey()); } @@ -4831,6 +4838,16 @@ bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vectorsecond.IsChange()) { + return nullptr; + } + return &address_book_it->second; +} + void CWallet::postInitProcess() { LOCK(cs_wallet); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 50dfb77d555d6..d2b30f138ab1a 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -187,14 +187,23 @@ class ReserveDestination /** Address book data */ class CAddressBookData { +private: + bool m_change{true}; + std::string m_label; public: - std::string name; + const std::string& name; std::string purpose; - CAddressBookData() : purpose("unknown") {} + CAddressBookData() : name(m_label), purpose("unknown") {} typedef std::map StringMap; StringMap destdata; + + bool IsChange() const { return m_change; } + void SetLabel(const std::string& label) { + m_change = false; + m_label = label; + } }; struct CRecipient @@ -847,7 +856,8 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati int64_t nOrderPosNext GUARDED_BY(cs_wallet) = 0; uint64_t nAccountingEntryNumber = 0; - std::map mapAddressBook GUARDED_BY(cs_wallet); + std::map m_address_book GUARDED_BY(cs_wallet); + const CAddressBookData* FindAddressBookEntry(const CTxDestination&, bool allow_change = false) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); std::set setLockedCoins GUARDED_BY(cs_wallet); @@ -933,7 +943,10 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati bool LoadMinVersion(int nVersion) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } - //! Adds a destination data tuple to the store, and saves it to disk + /** + * Adds a destination data tuple to the store, and saves it to disk + * When adding new fields, take care to consider how DelAddressBook should handle it! + */ bool AddDestData(WalletBatch& batch, const CTxDestination& dest, const std::string& key, const std::string& value) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); //! Erases a destination data tuple in the store and on disk bool EraseDestData(WalletBatch& batch, const CTxDestination& dest, const std::string& key) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 90eb2c634217a..eff739823c17c 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -243,11 +243,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, if (strType == DBKeys::NAME) { std::string strAddress; ssKey >> strAddress; - ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name; + std::string label; + ssValue >> label; + pwallet->m_address_book[DecodeDestination(strAddress)].SetLabel(label); } else if (strType == DBKeys::PURPOSE) { std::string strAddress; ssKey >> strAddress; - ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose; + ssValue >> pwallet->m_address_book[DecodeDestination(strAddress)].purpose; } else if (strType == DBKeys::TX) { uint256 hash; ssKey >> hash; diff --git a/src/wallet/wallettool.cpp b/src/wallet/wallettool.cpp index 2e75b0780163c..e574a2a827c89 100644 --- a/src/wallet/wallettool.cpp +++ b/src/wallet/wallettool.cpp @@ -101,7 +101,7 @@ static void WalletShowInfo(CWallet* wallet_instance) tfm::format(std::cout, "HD (hd seed available): %s\n", wallet_instance->IsHDEnabled() ? "yes" : "no"); tfm::format(std::cout, "Keypool Size: %u\n", wallet_instance->GetKeyPoolSize()); tfm::format(std::cout, "Transactions: %zu\n", wallet_instance->mapWallet.size()); - tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->mapAddressBook.size()); + tfm::format(std::cout, "Address Book: %zu\n", wallet_instance->m_address_book.size()); } bool ExecuteWalletToolFunc(const std::string& command, const std::string& name) diff --git a/test/README.md b/test/README.md index f1a869eb1bae9..eb8a2fc71dfc6 100644 --- a/test/README.md +++ b/test/README.md @@ -157,7 +157,7 @@ levels using the logger included in the test_framework, e.g. `test_framework.log` and no logs are output to the console. - when run directly, *all* logs are written to `test_framework.log` and INFO level and above are output to the console. -- when run on Travis, no logs are output to the console. However, if a test +- when run by [our CI (Continuous Integration)](/ci/README.md), no logs are output to the console. However, if a test fails, the `test_framework.log` and dashd `debug.log`s will all be dumped to the console to help troubleshooting. diff --git a/test/functional/README.md b/test/functional/README.md index 155ef1bbe932e..60867ac62cd94 100644 --- a/test/functional/README.md +++ b/test/functional/README.md @@ -51,10 +51,13 @@ don't have test cases for. #### General test-writing advice +- Instead of inline comments or no test documentation at all, log the comments to the test log, e.g. + `self.log.info('Create enough transactions to fill a block')`. Logs make the test code easier to read and the test + logic easier [to debug](/test/README.md#test-logging). - Set `self.num_nodes` to the minimum number of nodes necessary for the test. Having additional unrequired nodes adds to the execution time of the test as well as memory/CPU/disk requirements (which is important when running tests in - parallel or on Travis). + parallel). - Avoid stop-starting the nodes multiple times during the test if possible. A stop-start takes several seconds, so doing it several times blows up the runtime of the test. diff --git a/test/functional/rpc_getaddressinfo_label_deprecation.py b/test/functional/rpc_getaddressinfo_label_deprecation.py new file mode 100755 index 0000000000000..5e739ebede51a --- /dev/null +++ b/test/functional/rpc_getaddressinfo_label_deprecation.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# Copyright (c) 2020 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +""" +Test deprecation of the RPC getaddressinfo `label` field. It has been +superceded by the `labels` field. + +""" +from test_framework.test_framework import BitcoinTestFramework + +class GetAddressInfoLabelDeprecationTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 2 + self.setup_clean_chain = False + # Start node[0] with -deprecatedrpc=label, and node[1] without. + self.extra_args = [["-deprecatedrpc=label"], []] + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def test_label_with_deprecatedrpc_flag(self): + self.log.info("Test getaddressinfo label with -deprecatedrpc flag") + node = self.nodes[0] + address = node.getnewaddress() + info = node.getaddressinfo(address) + assert "label" in info + + def test_label_without_deprecatedrpc_flag(self): + self.log.info("Test getaddressinfo label without -deprecatedrpc flag") + node = self.nodes[1] + address = node.getnewaddress() + info = node.getaddressinfo(address) + assert "label" not in info + + def run_test(self): + """Test getaddressinfo label with and without -deprecatedrpc flag.""" + self.test_label_with_deprecatedrpc_flag() + self.test_label_without_deprecatedrpc_flag() + + +if __name__ == '__main__': + GetAddressInfoLabelDeprecationTest().main() diff --git a/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py b/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py index 1049440d49013..903f5536b91cc 100755 --- a/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py +++ b/test/functional/rpc_getaddressinfo_labels_purpose_deprecation.py @@ -4,8 +4,8 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """ Test deprecation of RPC getaddressinfo `labels` returning an array -containing a JSON hash of `name` and purpose` key-value pairs. It now -returns an array of label names. +containing a JSON object of `name` and purpose` key-value pairs. It now +returns an array containing only the label name. """ from test_framework.test_framework import BitcoinTestFramework diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py index fa93c1e3a4de5..d0037580bb2e8 100755 --- a/test/functional/rpc_psbt.py +++ b/test/functional/rpc_psbt.py @@ -329,6 +329,13 @@ def test_psbt_input_keys(psbt_input, keys): assert_equal(analysis['next'], 'creator') assert_equal(analysis['error'], 'PSBT is not valid. Input 0 has invalid value') + self.log.info("PSBT with signed, but not finalized, inputs should have Finalizer as next") + analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAXfx5nfVEBDq0BbpUjqqfvNEWyX2dGCkx7RiW9E6DXPbAAAAAAD9////AlDDAAAAAAAAFgAUy/UxxZuzZswcmFnN/E9DGSiHLUsuGPUFAAAAABYAFLsH5o0R38wXx+X2cCosTMCZnQ4baAAAAAABACwCAAAAAAEA4fUFAAAAABl2qRTgSNoebYX9/i35W9ixgrFUmcLJbYisAAAAACICAv4uHbVQEQkVrUThtBx6BnGlZJcyVHMKOYaJoBpEjQJyRzBEAiBse8ynDCBq+3BBEvQUeCnbf6cz0yt3ylnBsgiV2+zFZwIgCzgYKpTB+BmwtRw4fx5spZjueH8hMuJSnXu/wU/z1scBAQMEAQAAACIGAv4uHbVQEQkVrUThtBx6BnGlZJcyVHMKOYaJoBpEjQJyGA8FaUNUAACAAQAAgAAAAIAAAAAAAAAAAAEBHwDh9QUAAAAAFgAU4EjaHm2F/f4t+VvYsYKxVJnCyW0AACICAv4IiIHn01IKyw4lEaIxhArVyFqGABpomkhcTjULKKv7GA8FaUNUAACAAQAAgAAAAIABAAAAAAAAAAA=') + # TODO update tx above. + # currently I can't figure out how to generate transaction, that would be valid and will show correct stage finalizer. + # currently it fails at `verify pubkey` for signer + # assert_equal(analysis['next'], 'finalizer') + analysis = self.nodes[0].analyzepsbt('cHNidP8BAHECAAAAAbmNr2X0Nc+2AtaXYjPu3kIFc3Cmj1aYy5WQs5yaUfRvAAAAAAD/////AgCAgWrj0AcAFgAUKNw0x8HRctAgmvoevm4u1SbN7XL87QKVAAAAABYAFPck4gF7iL4NL4wtfRAKgQbghiTUAAAAAAABABQCAAAAAAGghgEAAAAAAAFRAAAAAAEBHwDyBSoBAAAAFgAUlQO3F/Y8ejrjUcQ4E4Ai8Uw1OvYAAAA=') assert_equal(analysis['next'], 'creator') assert_equal(analysis['error'], 'PSBT is not valid. Output amount invalid') diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 9954ce7b0f7e1..506a473b3d7c8 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -266,6 +266,7 @@ 'feature_settings.py', 'rpc_getdescriptorinfo.py', 'rpc_getaddressinfo_labels_purpose_deprecation.py', + 'rpc_getaddressinfo_label_deprecation.py', 'rpc_help.py', 'feature_help.py', # Don't append tests at the end to avoid merge conflicts diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 7b42c2ef43a3f..a44483af08521 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -394,7 +394,7 @@ def run_test(self): for label in [u'рыба', u'𝅘𝅥𝅯']: addr = self.nodes[0].getnewaddress() self.nodes[0].setlabel(addr, label) - test_address(self.nodes[0], addr, label=label, labels=[label]) + test_address(self.nodes[0], addr, labels=[label]) assert label in self.nodes[0].listlabels() self.nodes[0].rpc.ensure_ascii = True # restore to default diff --git a/test/functional/wallet_import_with_label.py b/test/functional/wallet_import_with_label.py index 3158e220eaf1a..f00d5c7c6aa7a 100755 --- a/test/functional/wallet_import_with_label.py +++ b/test/functional/wallet_import_with_label.py @@ -36,7 +36,6 @@ def run_test(self): address, iswatchonly=True, ismine=False, - label=label, labels=[label]) self.log.info( @@ -45,7 +44,7 @@ def run_test(self): ) priv_key = self.nodes[0].dumpprivkey(address) self.nodes[1].importprivkey(priv_key) - test_address(self.nodes[1], address, label=label, labels=[label]) + test_address(self.nodes[1], address, labels=[label]) self.log.info( "Test importaddress without label and importprivkey with label." @@ -57,7 +56,6 @@ def run_test(self): address2, iswatchonly=True, ismine=False, - label="", labels=[""]) self.log.info( @@ -68,7 +66,7 @@ def run_test(self): label2 = "Test Label 2" self.nodes[1].importprivkey(priv_key2, label2) - test_address(self.nodes[1], address2, label=label2, labels=[label2]) + test_address(self.nodes[1], address2, labels=[label2]) self.log.info("Test importaddress with label and importprivkey with label.") self.log.info("Import a watch-only address with a label.") @@ -79,7 +77,6 @@ def run_test(self): address3, iswatchonly=True, ismine=False, - label=label3_addr, labels=[label3_addr]) self.log.info( @@ -90,7 +87,7 @@ def run_test(self): label3_priv = "Test Label 3 for importprivkey" self.nodes[1].importprivkey(priv_key3, label3_priv) - test_address(self.nodes[1], address3, label=label3_priv, labels=[label3_priv]) + test_address(self.nodes[1], address3, labels=[label3_priv]) self.log.info( "Test importprivkey won't label new dests with the same " @@ -104,7 +101,6 @@ def run_test(self): address4, iswatchonly=True, ismine=False, - label=label4_addr, labels=[label4_addr]) self.log.info( @@ -116,7 +112,7 @@ def run_test(self): priv_key4 = self.nodes[0].dumpprivkey(address4) self.nodes[1].importprivkey(priv_key4) - test_address(self.nodes[1], address4, label=label4_addr, labels=[label4_addr]) + test_address(self.nodes[1], address4, labels=[label4_addr]) self.stop_nodes() diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py index 76bd009c3259b..c1a2f76478517 100755 --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -502,7 +502,6 @@ def run_test(self): key.p2pkh_addr, solvable=True, ismine=False, - label=p2pkh_label, labels=[p2pkh_label]) # Test import fails if both desc and scriptPubKey are provided diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index 66c438af27782..d0c58910fbb9a 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -157,7 +157,7 @@ def verify(self, node): if self.receive_address is not None: assert self.receive_address in self.addresses for address in self.addresses: - test_address(node, address, label=self.name, labels=[self.name]) + test_address(node, address, labels=[self.name]) assert self.name in node.listlabels() assert_equal( node.getaddressesbylabel(self.name), diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py index dca4e94e8b81f..1b169832b9225 100755 --- a/test/functional/wallet_listreceivedby.py +++ b/test/functional/wallet_listreceivedby.py @@ -128,7 +128,7 @@ def run_test(self): # set pre-state label = '' address = self.nodes[1].getnewaddress() - test_address(self.nodes[1], address, label=label, labels=[label]) + test_address(self.nodes[1], address, labels=[label]) received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0] balance_by_label = self.nodes[1].getreceivedbylabel(label) diff --git a/test/lint/extended-lint-cppcheck.sh b/test/lint/extended-lint-cppcheck.sh index a387fdb4a9fe1..8c001754e1fa8 100755 --- a/test/lint/extended-lint-cppcheck.sh +++ b/test/lint/extended-lint-cppcheck.sh @@ -66,7 +66,7 @@ function join_array { ENABLED_CHECKS_REGEXP=$(join_array "|" "${ENABLED_CHECKS[@]}") IGNORED_WARNINGS_REGEXP=$(join_array "|" "${IGNORED_WARNINGS[@]}") WARNINGS=$(git ls-files -- "*.cpp" "*.h" ":(exclude)src/dashbls/" ":(exclude)src/leveldb/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/" | \ - xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++11 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -DHAVE_WORKING_BOOST_SLEEP_FOR -I src/ -q 2>&1 | sort -u | \ + xargs cppcheck --enable=all -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++11 --template=gcc -D__cplusplus -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -I src/ -q 2>&1 | sort -u | \ grep -E "${ENABLED_CHECKS_REGEXP}" | \ grep -vE "${IGNORED_WARNINGS_REGEXP}") if [[ ${WARNINGS} != "" ]]; then diff --git a/test/lint/lint-cppcheck-dash.sh b/test/lint/lint-cppcheck-dash.sh index a6f54fcbf2a31..af1bce5cdcce1 100755 --- a/test/lint/lint-cppcheck-dash.sh +++ b/test/lint/lint-cppcheck-dash.sh @@ -120,7 +120,7 @@ then mkdir $CPPCHECK_DIR fi WARNINGS=$(echo "${FILES}" | \ - xargs cppcheck --enable=all --inline-suppr --cppcheck-build-dir=$CPPCHECK_DIR -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++17 --template=gcc -D__cplusplus -DENABLE_WALLET -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -DHAVE_WORKING_BOOST_SLEEP_FOR -DCHAR_BIT=8 -I src/ -q 2>&1 | sort -u | \ + xargs cppcheck --enable=all --inline-suppr --cppcheck-build-dir=$CPPCHECK_DIR -j "$(getconf _NPROCESSORS_ONLN)" --language=c++ --std=c++17 --template=gcc -D__cplusplus -DENABLE_WALLET -DCLIENT_VERSION_BUILD -DCLIENT_VERSION_IS_RELEASE -DCLIENT_VERSION_MAJOR -DCLIENT_VERSION_MINOR -DCOPYRIGHT_YEAR -DDEBUG -DCHAR_BIT=8 -I src/ -q 2>&1 | sort -u | \ grep -E "${ENABLED_CHECKS_REGEXP}" | \ grep -vE "${IGNORED_WARNINGS_REGEXP}" | \ grep -E "${FILES_REGEXP}")