diff --git a/src/clientversion.cpp b/src/clientversion.cpp index 148577ef25c08..d241a9fa34c51 100644 --- a/src/clientversion.cpp +++ b/src/clientversion.cpp @@ -65,11 +65,26 @@ std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::ostringstream ss; ss << "/"; ss << name << ":" << FormatVersion(nClientVersion); - if (!comments.empty()) - { + if (!comments.empty()) { std::vector::const_iterator it(comments.begin()); ss << "(" << *it; - for(++it; it != comments.end(); ++it) + for (++it; it != comments.end(); ++it) + ss << "; " << *it; + ss << ")"; + } + ss << "/"; + return ss.str(); +} + +std::string FormatSubVersion(const std::string& name, const std::string& strClientVersion, const std::vector& comments) +{ + std::ostringstream ss; + ss << "/"; + ss << name << ":" << strClientVersion; + if (!comments.empty()) { + std::vector::const_iterator it(comments.begin()); + ss << "(" << *it; + for (++it; it != comments.end(); ++it) ss << "; " << *it; ss << ")"; } diff --git a/src/clientversion.h b/src/clientversion.h index 71328135c4e2e..dc1c82a1cdc9b 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -40,6 +40,7 @@ extern const std::string CLIENT_NAME; std::string FormatFullVersion(); std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments); +std::string FormatSubVersion(const std::string& name, const std::string& strClientVersion, const std::vector& comments); std::string CopyrightHolders(const std::string& strPrefix); diff --git a/src/init.cpp b/src/init.cpp index 0f4800342ca8c..2ddb537155850 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1324,7 +1324,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt)); uacomments.push_back(cmt); } - strSubVersion = FormatFullVersion(); + strSubVersion = FormatSubVersion(CLIENT_NAME, FormatFullVersion(), uacomments); if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) { return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."), strSubVersion.size(), MAX_SUBVERSION_LENGTH)); diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index fbaef426c1898..deb9d5113c0d6 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -81,6 +81,9 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listtransactions", 1, "count" }, { "listtransactions", 2, "skip" }, { "listtransactions", 3, "include_watchonly" }, + { "listpendingtransactions", 1, "count" }, + { "listpendingtransactions", 2, "skip" }, + { "listpendingtransactions", 3, "include_watchonly" }, { "walletpassphrase", 1, "timeout" }, { "getblocktemplate", 0, "template_request" }, { "listsinceblock", 1, "target_confirmations" }, diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp index 87bad621052ab..c93c41a13853b 100644 --- a/src/wallet/rpc/wallet.cpp +++ b/src/wallet/rpc/wallet.cpp @@ -418,14 +418,14 @@ static RPCHelpMan createwallet() blsct::SeedType type = blsct::IMPORT_MASTER_KEY; if (!request.params[9].isNull() && request.params[9].isStr()) { seed = ParseHex(request.params[9].get_str()); - } - if (seed.size() == 160) { - seed = ParseHex(request.params[10].get_str()); - type = blsct::IMPORT_VIEW_KEY; - flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS; - } else if (seed.size() != 64) { - throw JSONRPCError(RPC_WALLET_ERROR, "Seed must be 64 (master) or 160 (view) characters long"); + if (seed.size() == 160) { + seed = ParseHex(request.params[10].get_str()); + type = blsct::IMPORT_VIEW_KEY; + flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS; + } else if (seed.size() != 64) { + throw JSONRPCError(RPC_WALLET_ERROR, "Seed must be 64 (master) or 160 (view) characters long"); + } } DatabaseOptions options; diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 9cfab1392cedf..32b8d49c38f86 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -672,7 +672,7 @@ def run_test(self): # Test gettransaction response with different arguments. self.log.info("Testing gettransaction response with different arguments...") self.nodes[0].setlabel(change, 'baz') - baz = self.nodes[0].listtransactions(label="baz", count=1)[0] + baz = self.nodes[0].listpendingtransactions(label="baz", count=1)[0] expected_receive_vout = {"label": "baz", "address": baz["address"], "amount": baz["amount"], diff --git a/test/functional/wallet_coinbase_category.py b/test/functional/wallet_coinbase_category.py index c2cb0bf3b07d6..34baece91b485 100755 --- a/test/functional/wallet_coinbase_category.py +++ b/test/functional/wallet_coinbase_category.py @@ -23,8 +23,13 @@ def set_test_params(self): def skip_test_if_missing_module(self): self.skip_if_no_wallet() - def assert_category(self, category, address, txid, skip): - assert_array_result(self.nodes[0].listtransactions(skip=skip), + def assert_category(self, category, address, txid, skip, pending=False): + if not pending: + assert_array_result(self.nodes[0].listtransactions(skip=skip), + {"address": address}, + {"category": category}) + else: + assert_array_result(self.nodes[0].listpendingtransactions(skip=skip), {"address": address}, {"category": category}) assert_array_result(self.nodes[0].listsinceblock()["transactions"], @@ -57,7 +62,7 @@ def run_test(self): # Orphan block that paid to address self.nodes[0].invalidateblock(hash) # Coinbase transaction is now orphaned - self.assert_category("orphan", address, txid, 100) + self.assert_category("orphan", address, txid, 100, True) if __name__ == '__main__': CoinbaseCategoryTest().main() diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py index a19a3ac2cbadf..c8db2b80d776a 100755 --- a/test/functional/wallet_listsinceblock.py +++ b/test/functional/wallet_listsinceblock.py @@ -54,7 +54,7 @@ def test_no_blockhash(self): self.log.info("Test no blockhash") txid = self.nodes[2].sendtoaddress(self.nodes[0].getnewaddress(), 1) self.sync_all() - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, { + assert_array_result(self.nodes[0].listpendingtransactions(), {"txid": txid}, { "category": "receive", "amount": 1, "confirmations": 0, diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py index 064ce12108878..2332d6c3ff201 100755 --- a/test/functional/wallet_listtransactions.py +++ b/test/functional/wallet_listtransactions.py @@ -40,7 +40,7 @@ def run_test(self): assert_array_result(self.nodes[0].listtransactions(), {"txid": txid}, {"category": "send", "amount": Decimal("-0.1"), "confirmations": 0, "trusted": True}) - assert_array_result(self.nodes[1].listtransactions(), + assert_array_result(self.nodes[1].listpendingtransactions(), {"txid": txid}, {"category": "receive", "amount": Decimal("0.1"), "confirmations": 0, "trusted": False}) self.log.info("Test confirmations change after mining a block") @@ -58,9 +58,6 @@ def run_test(self): assert_array_result(self.nodes[0].listtransactions(), {"txid": txid, "category": "send"}, {"amount": Decimal("-0.2")}) - assert_array_result(self.nodes[0].listtransactions(), - {"txid": txid, "category": "receive"}, - {"amount": Decimal("0.2")}) self.log.info("Test sendmany from node1: twice to self, twice to node0") send_to = {self.nodes[0].getnewaddress(): 0.11, @@ -72,27 +69,15 @@ def run_test(self): assert_array_result(self.nodes[1].listtransactions(), {"category": "send", "amount": Decimal("-0.11")}, {"txid": txid}) - assert_array_result(self.nodes[0].listtransactions(), - {"category": "receive", "amount": Decimal("0.11")}, - {"txid": txid}) assert_array_result(self.nodes[1].listtransactions(), {"category": "send", "amount": Decimal("-0.22")}, {"txid": txid}) - assert_array_result(self.nodes[1].listtransactions(), - {"category": "receive", "amount": Decimal("0.22")}, - {"txid": txid}) assert_array_result(self.nodes[1].listtransactions(), {"category": "send", "amount": Decimal("-0.33")}, {"txid": txid}) - assert_array_result(self.nodes[0].listtransactions(), - {"category": "receive", "amount": Decimal("0.33")}, - {"txid": txid}) assert_array_result(self.nodes[1].listtransactions(), {"category": "send", "amount": Decimal("-0.44")}, {"txid": txid}) - assert_array_result(self.nodes[1].listtransactions(), - {"category": "receive", "amount": Decimal("0.44")}, - {"txid": txid}) if not self.options.descriptors: # include_watchonly is a legacy wallet feature, so don't test it for descriptor wallets @@ -140,7 +125,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): assert not is_opt_in(self.nodes[0], txid_1) assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"}) self.sync_mempools() - assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"}) + assert_array_result(self.nodes[1].listpendingtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"}) # Tx2 will build off tx1, still not opting in to RBF. utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_1) @@ -159,7 +144,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): assert not is_opt_in(self.nodes[1], txid_2) assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"}) self.sync_mempools() - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"}) + assert_array_result(self.nodes[0].listpendingtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"}) self.log.info("Test txs with opt-in RBF (bip125-replaceable=yes)") # Tx3 will opt-in to RBF @@ -176,7 +161,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): assert is_opt_in(self.nodes[0], txid_3) assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"}) self.sync_mempools() - assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"}) + assert_array_result(self.nodes[1].listpendingtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"}) # Tx4 will chain off tx3. Doesn't signal itself, but depends on one # that does. @@ -190,7 +175,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): assert not is_opt_in(self.nodes[1], txid_4) assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"}) self.sync_mempools() - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"}) + assert_array_result(self.nodes[0].listpendingtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"}) self.log.info("Test tx with unknown RBF state (bip125-replaceable=unknown)") # Replace tx3, and check that tx4 becomes unknown @@ -201,7 +186,7 @@ def get_unconfirmed_utxo_entry(node, txid_to_match): txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, 0) assert is_opt_in(self.nodes[0], txid_3b) - assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"}) + assert_array_result(self.nodes[0].listpendingtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"}) self.sync_mempools() assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"})