mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-17 13:07:54 +02:00
Merge 244daa4821 into merged_master (Bitcoin PR #18607)
This commit is contained in:
commit
86082b9846
7 changed files with 48 additions and 21 deletions
|
|
@ -869,7 +869,7 @@ static UniValue getblock(const JSONRPCRequest& request)
|
|||
"If verbosity is 2, returns an Object with information about block <hash> and information about each transaction. \n",
|
||||
{
|
||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
|
||||
{"verbosity", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
|
||||
{"verbosity|verbose", RPCArg::Type::NUM, /* default */ "1", "0 for hex-encoded data, 1 for a json object, and 2 for json object with transaction data"},
|
||||
},
|
||||
{
|
||||
RPCResult{"for verbosity = 0",
|
||||
|
|
|
|||
|
|
@ -297,19 +297,19 @@ static UniValue generateblock(const JSONRPCRequest& request)
|
|||
RPCHelpMan{"generateblock",
|
||||
"\nMine a block with a set of ordered transactions immediately to a specified address or descriptor (before the RPC call returns)\n",
|
||||
{
|
||||
{"address/descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The address or descriptor to send the newly generated bitcoin to."},
|
||||
{"output", RPCArg::Type::STR, RPCArg::Optional::NO, "The address or descriptor to send the newly generated bitcoin to."},
|
||||
{"transactions", RPCArg::Type::ARR, RPCArg::Optional::NO, "An array of hex strings which are either txids or raw transactions.\n"
|
||||
"Txids must reference transactions currently in the mempool.\n"
|
||||
"All transactions must be valid and in valid order, otherwise the block will be rejected.",
|
||||
{
|
||||
{"rawtx/txid", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, ""},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::STR_HEX, "hash", "hash of generated block"}
|
||||
{RPCResult::Type::STR_HEX, "hash", "hash of generated block"},
|
||||
}
|
||||
},
|
||||
RPCExamples{
|
||||
|
|
@ -1699,7 +1699,7 @@ static const CRPCCommand commands[] =
|
|||
|
||||
{ "generating", "generatetoaddress", &generatetoaddress, {"nblocks","address","maxtries"} },
|
||||
{ "generating", "generatetodescriptor", &generatetodescriptor, {"num_blocks","descriptor","maxtries"} },
|
||||
{ "generating", "generateblock", &generateblock, {"address","transactions"} },
|
||||
{ "generating", "generateblock", &generateblock, {"output","transactions"} },
|
||||
|
||||
{ "util", "estimatesmartfee", &estimatesmartfee, {"conf_target", "estimate_mode"} },
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
#include <tuple>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
const std::string UNIX_EPOCH_TIME = "UNIX epoch time";
|
||||
const std::string EXAMPLE_ADDRESS[2] = {"bc1q09vm5lfy0j5reeulh4x5752q25uqqvz34hufdl", "bc1q02ad21edsxd23d32dfgqqsz4vv4nmtfzuklhy3"};
|
||||
|
||||
|
|
@ -341,7 +344,7 @@ struct Sections {
|
|||
if (outer_type == OuterType::NONE) return; // Nothing more to do for non-recursive types on first recursion
|
||||
auto left = indent;
|
||||
if (arg.m_type_str.size() != 0 && push_name) {
|
||||
left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0);
|
||||
left += "\"" + arg.GetName() + "\": " + arg.m_type_str.at(0);
|
||||
} else {
|
||||
left += push_name ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false);
|
||||
}
|
||||
|
|
@ -352,7 +355,7 @@ struct Sections {
|
|||
case RPCArg::Type::OBJ:
|
||||
case RPCArg::Type::OBJ_USER_KEYS: {
|
||||
const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
|
||||
PushSection({indent + (push_name ? "\"" + arg.m_name + "\": " : "") + "{", right});
|
||||
PushSection({indent + (push_name ? "\"" + arg.GetName() + "\": " : "") + "{", right});
|
||||
for (const auto& arg_inner : arg.m_inner) {
|
||||
Push(arg_inner, current_indent + 2, OuterType::OBJ);
|
||||
}
|
||||
|
|
@ -364,7 +367,7 @@ struct Sections {
|
|||
}
|
||||
case RPCArg::Type::ARR: {
|
||||
auto left = indent;
|
||||
left += push_name ? "\"" + arg.m_name + "\": " : "";
|
||||
left += push_name ? "\"" + arg.GetName() + "\": " : "";
|
||||
left += "[";
|
||||
const auto right = outer_type == OuterType::NONE ? "" : arg.ToDescriptionString();
|
||||
PushSection({left, right});
|
||||
|
|
@ -430,8 +433,12 @@ RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RP
|
|||
{
|
||||
std::set<std::string> named_args;
|
||||
for (const auto& arg : m_args) {
|
||||
std::vector<std::string> names;
|
||||
boost::split(names, arg.m_names, boost::is_any_of("|"));
|
||||
// Should have unique named arguments
|
||||
CHECK_NONFATAL(named_args.insert(arg.m_name).second);
|
||||
for (const std::string& name : names) {
|
||||
CHECK_NONFATAL(named_args.insert(name).second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -500,7 +507,7 @@ std::string RPCHelpMan::ToString() const
|
|||
if (i == 0) ret += "\nArguments:\n";
|
||||
|
||||
// Push named argument name and description
|
||||
sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.m_name, arg.ToDescriptionString());
|
||||
sections.m_sections.emplace_back(::ToString(i + 1) + ". " + arg.GetFirstName(), arg.ToDescriptionString());
|
||||
sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size());
|
||||
|
||||
// Recursively push nested args
|
||||
|
|
@ -517,6 +524,17 @@ std::string RPCHelpMan::ToString() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
std::string RPCArg::GetFirstName() const
|
||||
{
|
||||
return m_names.substr(0, m_names.find("|"));
|
||||
}
|
||||
|
||||
std::string RPCArg::GetName() const
|
||||
{
|
||||
CHECK_NONFATAL(std::string::npos == m_names.find("|"));
|
||||
return m_names;
|
||||
}
|
||||
|
||||
bool RPCArg::IsOptional() const
|
||||
{
|
||||
if (m_fallback.which() == 1) {
|
||||
|
|
@ -692,7 +710,7 @@ std::string RPCArg::ToStringObj(const bool oneline) const
|
|||
{
|
||||
std::string res;
|
||||
res += "\"";
|
||||
res += m_name;
|
||||
res += GetFirstName();
|
||||
if (oneline) {
|
||||
res += "\":";
|
||||
} else {
|
||||
|
|
@ -734,13 +752,13 @@ std::string RPCArg::ToString(const bool oneline) const
|
|||
switch (m_type) {
|
||||
case Type::STR_HEX:
|
||||
case Type::STR: {
|
||||
return "\"" + m_name + "\"";
|
||||
return "\"" + GetFirstName() + "\"";
|
||||
}
|
||||
case Type::NUM:
|
||||
case Type::RANGE:
|
||||
case Type::AMOUNT:
|
||||
case Type::BOOL: {
|
||||
return m_name;
|
||||
return GetFirstName();
|
||||
}
|
||||
case Type::OBJ:
|
||||
case Type::OBJ_USER_KEYS: {
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ struct RPCArg {
|
|||
OMITTED,
|
||||
};
|
||||
using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>;
|
||||
const std::string m_name; //!< The name of the arg (can be empty for inner args)
|
||||
const std::string m_names; //!< The name of the arg (can be empty for inner args, can contain multiple aliases separated by | for named request arguments)
|
||||
const Type m_type;
|
||||
const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
|
||||
const Fallback m_fallback;
|
||||
|
|
@ -162,7 +162,7 @@ struct RPCArg {
|
|||
const std::string description,
|
||||
const std::string oneline_description = "",
|
||||
const std::vector<std::string> type_str = {})
|
||||
: m_name{std::move(name)},
|
||||
: m_names{std::move(name)},
|
||||
m_type{std::move(type)},
|
||||
m_fallback{std::move(fallback)},
|
||||
m_description{std::move(description)},
|
||||
|
|
@ -180,7 +180,7 @@ struct RPCArg {
|
|||
const std::vector<RPCArg> inner,
|
||||
const std::string oneline_description = "",
|
||||
const std::vector<std::string> type_str = {})
|
||||
: m_name{std::move(name)},
|
||||
: m_names{std::move(name)},
|
||||
m_type{std::move(type)},
|
||||
m_inner{std::move(inner)},
|
||||
m_fallback{std::move(fallback)},
|
||||
|
|
@ -193,6 +193,12 @@ struct RPCArg {
|
|||
|
||||
bool IsOptional() const;
|
||||
|
||||
/** Return the first of all aliases */
|
||||
std::string GetFirstName() const;
|
||||
|
||||
/** Return the name, throws when there are aliases */
|
||||
std::string GetName() const;
|
||||
|
||||
/**
|
||||
* Return the type string of the argument.
|
||||
* Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description).
|
||||
|
|
|
|||
|
|
@ -1622,8 +1622,8 @@ UniValue listtransactions(const JSONRPCRequest& request)
|
|||
"\nIf a label name is provided, this will return only incoming transactions paying to addresses with the specified label.\n"
|
||||
"\nReturns up to 'count' most recent transactions skipping the first 'from' transactions.\n",
|
||||
{
|
||||
{"label", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
|
||||
" with the specified label, or \"*\" to disable filtering and return all transactions."},
|
||||
{"label|dummy", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "If set, should be a valid label name to return only incoming transactions\n"
|
||||
"with the specified label, or \"*\" to disable filtering and return all transactions."},
|
||||
{"count", RPCArg::Type::NUM, /* default */ "10", "The number of transactions to return"},
|
||||
{"skip", RPCArg::Type::NUM, /* default */ "0", "The number of transactions to skip"},
|
||||
{"include_watchonly", RPCArg::Type::BOOL, /* default */ "true for watch-only wallets, otherwise false", "Include transactions to watch-only addresses (see 'importaddress')"},
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from test_framework.util import (
|
|||
assert_raises_rpc_error,
|
||||
)
|
||||
|
||||
|
||||
class GenerateBlockTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
|
|
@ -23,14 +24,14 @@ class GenerateBlockTest(BitcoinTestFramework):
|
|||
|
||||
self.log.info('Generate an empty block to address')
|
||||
address = node.getnewaddress()
|
||||
hash = node.generateblock(address, [])['hash']
|
||||
block = node.getblock(hash, 2)
|
||||
hash = node.generateblock(output=address, transactions=[])['hash']
|
||||
block = node.getblock(blockhash=hash, verbose=2)
|
||||
assert_equal(len(block['tx']), 1)
|
||||
assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
|
||||
|
||||
self.log.info('Generate an empty block to a descriptor')
|
||||
hash = node.generateblock('addr(' + address + ')', [])['hash']
|
||||
block = node.getblock(hash, 2)
|
||||
block = node.getblock(blockhash=hash, verbosity=2)
|
||||
assert_equal(len(block['tx']), 1)
|
||||
assert_equal(block['tx'][0]['vout'][0]['scriptPubKey']['addresses'][0], address)
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ class ListTransactionsTest(BitcoinTestFramework):
|
|||
txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
|
||||
self.nodes[1].generate(1)
|
||||
self.sync_all()
|
||||
assert_equal(len(self.nodes[0].listtransactions(label="watchonly", include_watchonly=True)), 1)
|
||||
assert_equal(len(self.nodes[0].listtransactions(dummy="watchonly", include_watchonly=True)), 1)
|
||||
assert len(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=False)) == 0
|
||||
assert_array_result(self.nodes[0].listtransactions(label="watchonly", count=100, include_watchonly=True),
|
||||
{"category": "receive", "amount": Decimal("0.1")},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue