diff --git a/cmake/script/GenerateHeaderFromJson.cmake b/cmake/script/GenerateHeaderFromJson.cmake index 4a3bddb323..384ac20d10 100644 --- a/cmake/script/GenerateHeaderFromJson.cmake +++ b/cmake/script/GenerateHeaderFromJson.cmake @@ -6,7 +6,7 @@ cmake_path(GET JSON_SOURCE_PATH STEM json_source_basename) file(READ ${JSON_SOURCE_PATH} hex_content HEX) string(REGEX REPLACE "................" "\\0\n" formatted_bytes "${hex_content}") -string(REGEX REPLACE "[^\n][^\n]" "0x\\0, " formatted_bytes "${formatted_bytes}") +string(REGEX REPLACE "[^\n][^\n]" "'\\\\x\\0'," formatted_bytes "${formatted_bytes}") set(header_content "#include diff --git a/cmake/script/GenerateHeaderFromRaw.cmake b/cmake/script/GenerateHeaderFromRaw.cmake index 638876ecea..d373d1c4f8 100644 --- a/cmake/script/GenerateHeaderFromRaw.cmake +++ b/cmake/script/GenerateHeaderFromRaw.cmake @@ -6,7 +6,7 @@ cmake_path(GET RAW_SOURCE_PATH STEM raw_source_basename) file(READ ${RAW_SOURCE_PATH} hex_content HEX) string(REGEX REPLACE "................" "\\0\n" formatted_bytes "${hex_content}") -string(REGEX REPLACE "[^\n][^\n]" "std::byte{0x\\0}, " formatted_bytes "${formatted_bytes}") +string(REGEX REPLACE "[^\n][^\n]" "std::byte{0x\\0}," formatted_bytes "${formatted_bytes}") set(header_content "#include diff --git a/doc/release-notes-28121.md b/doc/release-notes-28121.md new file mode 100644 index 0000000000..911b7c5620 --- /dev/null +++ b/doc/release-notes-28121.md @@ -0,0 +1,2 @@ +The RPC `testmempoolaccept` response now includes a "reject-details" field in some cases, +similar to the complete error messages returned by `sendrawtransaction` (#28121) \ No newline at end of file diff --git a/src/base58.cpp b/src/base58.cpp index f9165ed55f..cab99f0cb5 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -139,7 +139,7 @@ std::string EncodeBase58Check(Span input) // add 4-byte hash check to the end std::vector vch(input.begin(), input.end()); uint256 hash = Hash(vch); - vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4); + vch.insert(vch.end(), hash.data(), hash.data() + 4); return EncodeBase58(vch); } diff --git a/src/crypto/chacha20.cpp b/src/crypto/chacha20.cpp index 4feed862cb..e756e0431e 100644 --- a/src/crypto/chacha20.cpp +++ b/src/crypto/chacha20.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2022 The Bitcoin Core developers +// Copyright (c) 2017-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -25,14 +25,14 @@ void ChaCha20Aligned::SetKey(Span key) noexcept { assert(key.size() == KEYLEN); - input[0] = ReadLE32(UCharCast(key.data() + 0)); - input[1] = ReadLE32(UCharCast(key.data() + 4)); - input[2] = ReadLE32(UCharCast(key.data() + 8)); - input[3] = ReadLE32(UCharCast(key.data() + 12)); - input[4] = ReadLE32(UCharCast(key.data() + 16)); - input[5] = ReadLE32(UCharCast(key.data() + 20)); - input[6] = ReadLE32(UCharCast(key.data() + 24)); - input[7] = ReadLE32(UCharCast(key.data() + 28)); + input[0] = ReadLE32(key.data() + 0); + input[1] = ReadLE32(key.data() + 4); + input[2] = ReadLE32(key.data() + 8); + input[3] = ReadLE32(key.data() + 12); + input[4] = ReadLE32(key.data() + 16); + input[5] = ReadLE32(key.data() + 20); + input[6] = ReadLE32(key.data() + 24); + input[7] = ReadLE32(key.data() + 28); input[8] = 0; input[9] = 0; input[10] = 0; diff --git a/src/crypto/common.h b/src/crypto/common.h index d45459b1f6..f151cbb625 100644 --- a/src/crypto/common.h +++ b/src/crypto/common.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020 The Bitcoin Core developers +// Copyright (c) 2014-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -7,82 +7,99 @@ #include +#include +#include #include #include -uint16_t static inline ReadLE16(const unsigned char* ptr) +template +concept ByteType = std::same_as || std::same_as; + +template +inline uint16_t ReadLE16(const B* ptr) { uint16_t x; memcpy(&x, ptr, 2); return le16toh_internal(x); } -uint32_t static inline ReadLE32(const unsigned char* ptr) +template +inline uint32_t ReadLE32(const B* ptr) { uint32_t x; memcpy(&x, ptr, 4); return le32toh_internal(x); } -uint64_t static inline ReadLE64(const unsigned char* ptr) +template +inline uint64_t ReadLE64(const B* ptr) { uint64_t x; memcpy(&x, ptr, 8); return le64toh_internal(x); } -void static inline WriteLE16(unsigned char* ptr, uint16_t x) +template +inline void WriteLE16(B* ptr, uint16_t x) { uint16_t v = htole16_internal(x); memcpy(ptr, &v, 2); } -void static inline WriteLE32(unsigned char* ptr, uint32_t x) +template +inline void WriteLE32(B* ptr, uint32_t x) { uint32_t v = htole32_internal(x); memcpy(ptr, &v, 4); } -void static inline WriteLE64(unsigned char* ptr, uint64_t x) +template +inline void WriteLE64(B* ptr, uint64_t x) { uint64_t v = htole64_internal(x); memcpy(ptr, &v, 8); } -uint16_t static inline ReadBE16(const unsigned char* ptr) +template +inline uint16_t ReadBE16(const B* ptr) { uint16_t x; memcpy(&x, ptr, 2); return be16toh_internal(x); } -uint32_t static inline ReadBE32(const unsigned char* ptr) +template +inline uint32_t ReadBE32(const B* ptr) { uint32_t x; memcpy(&x, ptr, 4); return be32toh_internal(x); } -uint64_t static inline ReadBE64(const unsigned char* ptr) +template +inline uint64_t ReadBE64(const B* ptr) { uint64_t x; memcpy(&x, ptr, 8); return be64toh_internal(x); } -void static inline WriteBE16(unsigned char* ptr, uint16_t x) +template +inline void WriteBE16(B* ptr, uint16_t x) { uint16_t v = htobe16_internal(x); memcpy(ptr, &v, 2); } -void static inline WriteBE32(unsigned char* ptr, uint32_t x) +template +inline void WriteBE32(B* ptr, uint32_t x) { uint32_t v = htobe32_internal(x); memcpy(ptr, &v, 4); } -void static inline WriteBE64(unsigned char* ptr, uint64_t x) +template +inline void WriteBE64(B* ptr, uint64_t x) { uint64_t v = htobe64_internal(x); memcpy(ptr, &v, 8); diff --git a/src/httpserver.h b/src/httpserver.h index 33216a0119..6535dc6086 100644 --- a/src/httpserver.h +++ b/src/httpserver.h @@ -14,8 +14,17 @@ namespace util { class SignalInterrupt; } // namespace util -static const int DEFAULT_HTTP_THREADS=4; -static const int DEFAULT_HTTP_WORKQUEUE=16; +/** + * The default value for `-rpcthreads`. This number of threads will be created at startup. + */ +static const int DEFAULT_HTTP_THREADS=16; + +/** + * The default value for `-rpcworkqueue`. This is the maximum depth of the work queue, + * we don't allocate this number of work queue items upfront. + */ +static const int DEFAULT_HTTP_WORKQUEUE=64; + static const int DEFAULT_HTTP_SERVER_TIMEOUT=30; struct evhttp_request; diff --git a/src/init.cpp b/src/init.cpp index f4b842bebb..b5adcf6476 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -665,7 +665,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc) argsman.AddArg("-rpcuser=", "Username for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC); argsman.AddArg("-rpcwhitelist=", "Set a whitelist to filter incoming RPC calls for a specific user. The field comes in the format: :,,...,. If multiple whitelists are set for a given user, they are set-intersected. See -rpcwhitelistdefault documentation for information on default whitelist behavior.", ArgsManager::ALLOW_ANY, OptionsCategory::RPC); argsman.AddArg("-rpcwhitelistdefault", "Sets default behavior for rpc whitelisting. Unless rpcwhitelistdefault is set to 0, if any -rpcwhitelist is set, the rpc server acts as if all rpc users are subject to empty-unless-otherwise-specified whitelists. If rpcwhitelistdefault is set to 1 and no -rpcwhitelist is set, rpc server acts as if all rpc users are subject to empty whitelists.", ArgsManager::ALLOW_ANY, OptionsCategory::RPC); - argsman.AddArg("-rpcworkqueue=", strprintf("Set the depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC); + argsman.AddArg("-rpcworkqueue=", strprintf("Set the maximum depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC); argsman.AddArg("-server", "Accept command line and JSON-RPC commands", ArgsManager::ALLOW_ANY, OptionsCategory::RPC); if (can_listen_ipc) { argsman.AddArg("-ipcbind=
", "Bind to Unix socket address and listen for incoming connections. Valid address values are \"unix\" to listen on the default path, /node.sock, or \"unix:/custom/path\" to specify a custom path. Can be specified multiple times to listen on multiple paths. Default behavior is not to listen on any path. If relative paths are specified, they are interpreted relative to the network data directory. If paths include any parent directory components and the parent directories do not exist, they will be created.", ArgsManager::ALLOW_ANY, OptionsCategory::IPC); diff --git a/src/policy/rbf.cpp b/src/policy/rbf.cpp index b634dea561..bc76361fba 100644 --- a/src/policy/rbf.cpp +++ b/src/policy/rbf.cpp @@ -71,7 +71,7 @@ std::optional GetEntriesForConflicts(const CTransaction& tx, // descendants (i.e. if multiple conflicts share a descendant, it will be counted multiple // times), but we just want to be conservative to avoid doing too much work. if (nConflictingCount > MAX_REPLACEMENT_CANDIDATES) { - return strprintf("rejecting replacement %s; too many potential replacements (%d > %d)\n", + return strprintf("rejecting replacement %s; too many potential replacements (%d > %d)", txid.ToString(), nConflictingCount, MAX_REPLACEMENT_CANDIDATES); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index d2805530ef..035d031034 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1393,6 +1393,7 @@ RPCHelpMan getblockchaininfo() {RPCResult::Type::NUM, "pruneheight", /*optional=*/true, "height of the last block pruned, plus one (only present if pruning is enabled)"}, {RPCResult::Type::BOOL, "automatic_pruning", /*optional=*/true, "whether automatic pruning is enabled (only present if pruning is enabled)"}, {RPCResult::Type::NUM, "prune_target_size", /*optional=*/true, "the target size used by pruning (only present if automatic pruning is enabled)"}, + {RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "the block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)"}, (IsDeprecatedRPCEnabled("warnings") ? RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} : RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)", @@ -1437,6 +1438,11 @@ RPCHelpMan getblockchaininfo() obj.pushKV("prune_target_size", chainman.m_blockman.GetPruneTarget()); } } + if (chainman.GetParams().GetChainType() == ChainType::SIGNET) { + const std::vector& signet_challenge = + chainman.GetParams().GetConsensus().signet_challenge; + obj.pushKV("signet_challenge", HexStr(signet_challenge)); + } NodeContext& node = EnsureAnyNodeContext(request.context); obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings"))); diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 6d462a7e85..52260d5794 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -146,7 +146,8 @@ static RPCHelpMan testmempoolaccept() {RPCResult{RPCResult::Type::STR_HEX, "", "transaction wtxid in hex"}, }}, }}, - {RPCResult::Type::STR, "reject-reason", /*optional=*/true, "Rejection string (only present when 'allowed' is false)"}, + {RPCResult::Type::STR, "reject-reason", /*optional=*/true, "Rejection reason (only present when 'allowed' is false)"}, + {RPCResult::Type::STR, "reject-details", /*optional=*/true, "Rejection details (only present when 'allowed' is false and rejection details exist)"}, }}, } }, @@ -245,6 +246,7 @@ static RPCHelpMan testmempoolaccept() result_inner.pushKV("reject-reason", "missing-inputs"); } else { result_inner.pushKV("reject-reason", state.GetRejectReason()); + result_inner.pushKV("reject-details", state.ToString()); } } rpc_result.push_back(std::move(result_inner)); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 74e4c31df0..ad946888d4 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2010 Satoshi Nakamoto -// Copyright (c) 2009-2022 The Bitcoin Core developers +// Copyright (c) 2009-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -374,22 +374,22 @@ static RPCHelpMan generateblock() ChainstateManager& chainman = EnsureChainman(node); { - std::unique_ptr block_template{miner.createNewBlock({.use_mempool = false, .coinbase_output_script = coinbase_output_script})}; - CHECK_NONFATAL(block_template); + LOCK(chainman.GetMutex()); + { + std::unique_ptr block_template{miner.createNewBlock({.use_mempool = false, .coinbase_output_script = coinbase_output_script})}; + CHECK_NONFATAL(block_template); - block = block_template->getBlock(); - } + block = block_template->getBlock(); + } - CHECK_NONFATAL(block.vtx.size() == 1); + CHECK_NONFATAL(block.vtx.size() == 1); - // Add transactions - block.vtx.insert(block.vtx.end(), txs.begin(), txs.end()); - RegenerateCommitments(block, chainman); + // Add transactions + block.vtx.insert(block.vtx.end(), txs.begin(), txs.end()); + RegenerateCommitments(block, chainman); - { - LOCK(::cs_main); BlockValidationState state; - if (!TestBlockValidity(state, chainman.GetParams(), chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), /*fCheckPOW=*/false, /*fCheckMerkleRoot=*/false)) { + if (!TestBlockValidity(state, chainman.GetParams(), chainman.ActiveChainstate(), block, chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), /*fCheckPOW=*/false, /*fCheckMerkleRoot=*/false)) { throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.ToString())); } } @@ -428,6 +428,7 @@ static RPCHelpMan getmininginfo() {RPCResult::Type::NUM, "networkhashps", "The network hashes per second"}, {RPCResult::Type::NUM, "pooledtx", "The size of the mempool"}, {RPCResult::Type::STR, "chain", "current network name (" LIST_CHAIN_NAMES ")"}, + {RPCResult::Type::STR_HEX, "signet_challenge", /*optional=*/true, "The block challenge (aka. block script), in hexadecimal (only present if the current network is a signet)"}, (IsDeprecatedRPCEnabled("warnings") ? RPCResult{RPCResult::Type::STR, "warnings", "any network and blockchain warnings (DEPRECATED)"} : RPCResult{RPCResult::Type::ARR, "warnings", "any network and blockchain warnings (run with `-deprecatedrpc=warnings` to return the latest warning as a single string)", @@ -457,6 +458,11 @@ static RPCHelpMan getmininginfo() obj.pushKV("networkhashps", getnetworkhashps().HandleRequest(request)); obj.pushKV("pooledtx", (uint64_t)mempool.size()); obj.pushKV("chain", chainman.GetParams().GetChainTypeString()); + if (chainman.GetParams().GetChainType() == ChainType::SIGNET) { + const std::vector& signet_challenge = + chainman.GetParams().GetConsensus().signet_challenge; + obj.pushKV("signet_challenge", HexStr(signet_challenge)); + } obj.pushKV("warnings", node::GetWarningsForRpc(*CHECK_NONFATAL(node.warnings), IsDeprecatedRPCEnabled("warnings"))); return obj; }, diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index 5026470edc..2e1a30744e 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -1761,7 +1761,7 @@ struct KeyParser { std::vector> ParseScript(uint32_t& key_exp_index, Span& sp, ParseScriptContext ctx, FlatSigningProvider& out, std::string& error) { using namespace script; - + Assume(ctx == ParseScriptContext::TOP || ctx == ParseScriptContext::P2SH || ctx == ParseScriptContext::P2WSH || ctx == ParseScriptContext::P2TR); std::vector> ret; auto expr = Expr(sp); if (Func("pk", expr)) { @@ -1787,10 +1787,6 @@ std::vector> ParseScript(uint32_t& key_exp_index ret.emplace_back(std::make_unique(std::move(pubkey))); } return ret; - } else if (ctx != ParseScriptContext::P2TR && Func("pkh", expr)) { - // Under Taproot, always the Miniscript parser deal with it. - error = "Can only have pkh at top level, in sh(), wsh(), or in tr()"; - return {}; } if (ctx == ParseScriptContext::TOP && Func("combo", expr)) { auto pubkeys = ParsePubkey(key_exp_index, expr, ctx, out, error); diff --git a/src/script/miniscript.h b/src/script/miniscript.h index e739d8031f..75f978457c 100644 --- a/src/script/miniscript.h +++ b/src/script/miniscript.h @@ -1798,7 +1798,7 @@ inline NodeRef Parse(Span in, const Ctx& ctx) // Get threshold int next_comma = FindNextChar(in, ','); if (next_comma < 1) return false; - const auto k_to_integral{ToIntegral(std::string_view(in.begin(), next_comma))}; + const auto k_to_integral{ToIntegral(std::string_view(in.data(), next_comma))}; if (!k_to_integral.has_value()) return false; const int64_t k{k_to_integral.value()}; in = in.subspan(next_comma + 1); @@ -1954,7 +1954,7 @@ inline NodeRef Parse(Span in, const Ctx& ctx) } else if (Const("after(", in)) { int arg_size = FindNextChar(in, ')'); if (arg_size < 1) return {}; - const auto num{ToIntegral(std::string_view(in.begin(), arg_size))}; + const auto num{ToIntegral(std::string_view(in.data(), arg_size))}; if (!num.has_value() || *num < 1 || *num >= 0x80000000L) return {}; constructed.push_back(MakeNodeRef(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AFTER, *num)); in = in.subspan(arg_size + 1); @@ -1962,7 +1962,7 @@ inline NodeRef Parse(Span in, const Ctx& ctx) } else if (Const("older(", in)) { int arg_size = FindNextChar(in, ')'); if (arg_size < 1) return {}; - const auto num{ToIntegral(std::string_view(in.begin(), arg_size))}; + const auto num{ToIntegral(std::string_view(in.data(), arg_size))}; if (!num.has_value() || *num < 1 || *num >= 0x80000000L) return {}; constructed.push_back(MakeNodeRef(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, *num)); in = in.subspan(arg_size + 1); @@ -1974,7 +1974,7 @@ inline NodeRef Parse(Span in, const Ctx& ctx) } else if (Const("thresh(", in)) { int next_comma = FindNextChar(in, ','); if (next_comma < 1) return {}; - const auto k{ToIntegral(std::string_view(in.begin(), next_comma))}; + const auto k{ToIntegral(std::string_view(in.data(), next_comma))}; if (!k.has_value() || *k < 1) return {}; in = in.subspan(next_comma + 1); // n = 1 here because we read the first WRAPPED_EXPR before reaching THRESH diff --git a/src/script/solver.h b/src/script/solver.h index 5a7b685a6f..5b945477c9 100644 --- a/src/script/solver.h +++ b/src/script/solver.h @@ -10,6 +10,7 @@ #include #include