diff --git a/src/pubkey.h b/src/pubkey.h index 990a33ccef99..5de7fa9519a8 100644 --- a/src/pubkey.h +++ b/src/pubkey.h @@ -181,6 +181,12 @@ class CPubKey return size() > 0; } + /** Check if a public key is a syntactically valid compressed or uncompressed key. */ + bool IsValidNonHybrid() const noexcept + { + return size() > 0 && (vch[0] == 0x02 || vch[0] == 0x03 || vch[0] == 0x04); + } + //! fully validate whether this is a valid public key (more expensive than IsValid()) bool IsFullyValid() const; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 24b63fe83eec..2474038e2211 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -559,6 +559,8 @@ static RPCHelpMan getblocktemplate() {"str", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "client side supported softfork deployment"}, }, }, + {"longpollid", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "delay processing request until the result would vary significantly from the \"longpollid\" of a prior template"}, + {"data", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "proposed block data to check, encoded in hexadecimal; valid only for mode=\"proposal\""}, }, "\"template_request\""}, }, diff --git a/src/script/descriptor.cpp b/src/script/descriptor.cpp index e432ce3943fc..bdf6252d868e 100644 --- a/src/script/descriptor.cpp +++ b/src/script/descriptor.cpp @@ -869,6 +869,10 @@ std::unique_ptr ParsePubkeyInner(uint32_t key_exp_index, const S if (IsHex(str)) { std::vector data = ParseHex(str); CPubKey pubkey(data); + if (pubkey.IsValid() && !pubkey.IsValidNonHybrid()) { + error = "Hybrid public keys are not allowed"; + return nullptr; + } if (pubkey.IsFullyValid()) { if (permit_uncompressed || pubkey.IsCompressed()) { return std::make_unique(key_exp_index, pubkey); @@ -1096,7 +1100,7 @@ std::unique_ptr InferScript(const CScript& script, ParseScriptCo if (txntype == TxoutType::PUBKEY) { CPubKey pubkey(data[0]); - if (pubkey.IsValid()) { + if (pubkey.IsValidNonHybrid()) { return std::make_unique(InferPubkey(pubkey, ctx, provider)); } } diff --git a/src/test/descriptor_tests.cpp b/src/test/descriptor_tests.cpp index 927d5551baea..69c03ccddf71 100644 --- a/src/test/descriptor_tests.cpp +++ b/src/test/descriptor_tests.cpp @@ -293,6 +293,11 @@ BOOST_AUTO_TEST_CASE(descriptor_test) Check("pkh(7sH936MDoVPFVk2VoaCM5yW8P3BfPyffnZECyaHrZwfLgWpS13e)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pkh(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"76a914b5bd079c4d57cc7fc28ecf8213a6b791625b818388ac"}}, OutputType::LEGACY); Check("combo(7sH936MDoVPFVk2VoaCM5yW8P3BfPyffnZECyaHrZwfLgWpS13e)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", SIGNABLE, {{"4104a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235ac"}}, OutputType::LEGACY); + // Equivalent single-key hybrid is not allowed + CheckUnparsable("", "combo(07a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "combo(): Hybrid public keys are not allowed"); + CheckUnparsable("", "pk(0623542d61708e3fc48ba78fbe8fcc983ba94a520bc33f82b8e45e51dbc47af2726bcf181925eee1bdd868b109314f3ea92a6fc23d6b66057d3acfba04d6b08b58)", "pk(): Hybrid public keys are not allowed"); + CheckUnparsable("", "pkh(07a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)", "pkh(): Hybrid public keys are not allowed"); + // Some unconventional single-key constructions Check("sh(pk(XJvEUEcFWCHCyruc8ZX5exPZaGe4UR7gC5FHrhwPnQGDs1uWCsT2))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(pk(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141857af51a5e516552b3086430fd8ce55f7c1a52487"}}, OutputType::LEGACY); Check("sh(pkh(XJvEUEcFWCHCyruc8ZX5exPZaGe4UR7gC5FHrhwPnQGDs1uWCsT2))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", "sh(pkh(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))", SIGNABLE, {{"a9141a31ad23bf49c247dd531a623c2ef57da3c400c587"}}, OutputType::LEGACY); diff --git a/src/validation.cpp b/src/validation.cpp index 06d45ca61bcb..6073f5cc7d0e 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3111,9 +3111,11 @@ CBlockIndex* CChainState::FindMostWorkChain() while (pindexTest != pindexFailed) { if (fFailedChain) { pindexFailed->nStatus |= BLOCK_FAILED_CHILD; + m_blockman.m_dirty_blockindex.insert(pindexFailed); } else if (fConflictingChain) { // We don't need data for conflciting blocks pindexFailed->nStatus |= BLOCK_CONFLICT_CHAINLOCK; + m_blockman.m_dirty_blockindex.insert(pindexFailed); } else if (fMissingData) { // If we're missing data, then add back to m_blocks_unlinked, // so that if the block arrives in the future we can try adding