Merge #6149: backport: trivial 2024 07 23

d4a728b60d docs: add release notes for 24806 (pasta)
1221f45a9c Merge bitcoin/bitcoin#25314: p2p: always set nTime for self-advertisements (laanwj)
c2b3f4b62f Merge bitcoin/bitcoin#25299: doc: Correct comments re. units of constants (laanwj)
1ecb6ca1d0 Merge bitcoin/bitcoin#25339: RPC/blockchain: Elaborate on scantxoutset documentation (MacroFake)
2afbf25e25 Merge bitcoin/bitcoin#24032: Add defaults to vDeployments to avoid uninitialized variables (laanwj)
1d991ae96b Merge bitcoin/bitcoin#24806: RPC: Switch getblockfrompeer back to standard param name blockhash (fanquake)
9ee82d223e Merge bitcoin/bitcoin#24627: test: Limit scope of id global which is shared between subtests (fanquake)
5587bf15db Merge bitcoin/bitcoin#24156: build: Replace `which` command with `command -v` (laanwj)
5a6a328c32 Merge bitcoin/bitcoin#23219: p2p, refactor: tidy up LookupSubNet() (W. J. van der Laan)
e311662a2d Merge bitcoin/bitcoin#23766: refactor: remove unneeded calls to strprintf() (MarcoFalke)
763645ad2b Merge bitcoin/bitcoin#23634: rpc: add missing scantxoutset examples (W. J. van der Laan)
5ac73929e2 Merge bitcoin/bitcoin#20583: rpc: Add missing BlockUntilSyncedToCurrentChain to wallet RPCs (MarcoFalke)
cc9d00a56d Merge bitcoin/bitcoin#23132: test: Change background_cs from pointer to reference in validation_chainstate_tests (MarcoFalke)
5e0c67cb94 Merge bitcoin/bitcoin#22113: test: minor cleanups in feature_cltv.py (MarcoFalke)

Pull request description:

  ## Issue being fixed or feature implemented
  Batch of trivial backports

  ## What was done?

  ## How Has This Been Tested?
  building; ran tests that were changed

  ## Breaking Changes
    _Please describe any breaking changes your code introduces_

  ## Checklist:
    _Go over all the following points, and put an `x` in all the boxes that apply._
  - [ ] I have performed a self-review of my own code
  - [ ] I have commented my code, particularly in hard-to-understand areas
  - [ ] I have added or updated relevant unit/integration/functional/e2e tests
  - [ ] I have made corresponding changes to the documentation
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK d4a728b60d

Tree-SHA512: e602d10a6824aa285957bb8c41a554b85fcf2447cc137a33f30b6ea9e70845ad6e7cf3f9a12536135d86cc988c13e914b3ba18bf837639cd5e250d04e432a83a
This commit is contained in:
pasta 2024-07-25 09:17:30 -05:00
commit 7f0f30e29e
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
22 changed files with 123 additions and 94 deletions

View File

@ -1,4 +1,4 @@
ifneq ($(shell which $(host)-g++-posix),)
ifneq ($(shell $(SHELL) $(.SHELLFLAGS) "command -v $(host)-g++-posix"),)
mingw32_CXX := $(host)-g++-posix
endif

View File

@ -0,0 +1,5 @@
## RPC changes
- `getblockfrompeer`, introduced in v21.0.0, named argument `block_hash` has been
renamed `blockhash` to be aligned with the rest of the codebase. This is a breaking
change if using named parameters. (#6149)

View File

@ -46,11 +46,11 @@ constexpr bool ValidDeployment(DeploymentPos dep) { return DEPLOYMENT_TESTDUMMY
*/
struct BIP9Deployment {
/** Bit position to select the particular bit in nVersion. */
int bit;
int bit{28};
/** Start MedianTime for version bits miner confirmation. Can be a date in the past */
int64_t nStartTime;
int64_t nStartTime{NEVER_ACTIVE};
/** Timeout/expiry MedianTime for the deployment attempt. */
int64_t nTimeout;
int64_t nTimeout{NEVER_ACTIVE};
/** If lock in occurs, delay activation until at least this block
* height. Note that activation will only occur on a retarget
* boundary.

View File

@ -61,7 +61,7 @@ void AddLoggingArgs(ArgsManager& argsman)
argsman.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). "
"If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + LogInstance().LogCategoriesString() + ". This option can be specified multiple times to output multiple categories.",
ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except the specified category. This option can be specified multiple times to exclude multiple categories."), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-debugexclude=<category>", "Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except the specified category. This option can be specified multiple times to exclude multiple categories.", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
#ifdef HAVE_THREAD_LOCAL

View File

@ -273,7 +273,7 @@ std::optional<CAddress> GetLocalAddrForPeer(CNode *pnode)
if (pnode->IsInboundConn()) {
// For inbound connections, assume both the address and the port
// as seen from the peer.
addrLocal = CAddress{pnode->GetAddrLocal(), addrLocal.nServices};
addrLocal = CAddress{pnode->GetAddrLocal(), addrLocal.nServices, addrLocal.nTime};
} else {
// For outbound connections, assume just the address as seen from
// the peer and leave the port in `addrLocal` as returned by

View File

@ -681,40 +681,36 @@ bool ConnectThroughProxy(const Proxy& proxy, const std::string& strDest, uint16_
return true;
}
bool LookupSubNet(const std::string& strSubnet, CSubNet& ret, DNSLookupFn dns_lookup_function)
bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out)
{
if (!ValidAsCString(strSubnet)) {
if (!ValidAsCString(subnet_str)) {
return false;
}
size_t slash = strSubnet.find_last_of('/');
CNetAddr network;
std::string strAddress = strSubnet.substr(0, slash);
if (LookupHost(strAddress, network, false, dns_lookup_function))
{
if (slash != strSubnet.npos)
{
std::string strNetmask = strSubnet.substr(slash + 1);
uint8_t n;
if (ParseUInt8(strNetmask, &n)) {
// If valid number, assume CIDR variable-length subnet masking
ret = CSubNet(network, n);
return ret.IsValid();
}
else // If not a valid number, try full netmask syntax
{
CNetAddr netmask;
// Never allow lookup for netmask
if (LookupHost(strNetmask, netmask, false, dns_lookup_function)) {
ret = CSubNet(network, netmask);
return ret.IsValid();
const size_t slash_pos{subnet_str.find_last_of('/')};
const std::string str_addr{subnet_str.substr(0, slash_pos)};
CNetAddr addr;
if (LookupHost(str_addr, addr, /*fAllowLookup=*/false)) {
if (slash_pos != subnet_str.npos) {
const std::string netmask_str{subnet_str.substr(slash_pos + 1)};
uint8_t netmask;
if (ParseUInt8(netmask_str, &netmask)) {
// Valid number; assume CIDR variable-length subnet masking.
subnet_out = CSubNet{addr, netmask};
return subnet_out.IsValid();
} else {
// Invalid number; try full netmask syntax. Never allow lookup for netmask.
CNetAddr full_netmask;
if (LookupHost(netmask_str, full_netmask, /*fAllowLookup=*/false)) {
subnet_out = CSubNet{addr, full_netmask};
return subnet_out.IsValid();
}
}
}
else // Single IP subnet (<ipv4>/32 or <ipv6>/128)
{
ret = CSubNet(network);
return ret.IsValid();
} else {
// Single IP subnet (<ipv4>/32 or <ipv6>/128).
subnet_out = CSubNet{addr};
return subnet_out.IsValid();
}
}
return false;

View File

@ -173,13 +173,14 @@ CService LookupNumeric(const std::string& name, uint16_t portDefault = 0, DNSLoo
* Parse and resolve a specified subnet string into the appropriate internal
* representation.
*
* @param strSubnet A string representation of a subnet of the form `network
* address [ "/", ( CIDR-style suffix | netmask ) ]`(e.g.
* `2001:db8::/32`, `192.0.2.0/255.255.255.0`, or `8.8.8.8`).
*
* @returns Whether the operation succeeded or not.
* @param[in] subnet_str A string representation of a subnet of the form
* `network address [ "/", ( CIDR-style suffix | netmask ) ]`
* e.g. "2001:db8::/32", "192.0.2.0/255.255.255.0" or "8.8.8.8".
* @param[out] subnet_out Internal subnet representation, if parsable/resolvable
* from `subnet_str`.
* @returns whether the operation succeeded or not.
*/
bool LookupSubNet(const std::string& strSubnet, CSubNet& subnet, DNSLookupFn dns_lookup_function = g_dns_lookup);
bool LookupSubNet(const std::string& subnet_str, CSubNet& subnet_out);
/**
* Create a TCP socket in the given address family.

View File

@ -53,7 +53,7 @@ extern std::atomic_bool fReindex;
extern bool fHavePruned;
/** True if we're running in -prune mode. */
extern bool fPruneMode;
/** Number of MiB of block files that we're trying to stay below. */
/** Number of bytes of block files that we're trying to stay below. */
extern uint64_t nPruneTarget;
/** True if we're running in -addressindex mode. */

View File

@ -101,7 +101,7 @@ PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
}
);
if (!MoneyRange(out_amt)) {
result.SetInvalid(strprintf("PSBT is not valid. Output amount invalid"));
result.SetInvalid("PSBT is not valid. Output amount invalid");
return result;
}

View File

@ -39,7 +39,7 @@ static constexpr uint8_t PSBT_SEPARATOR = 0x00;
// BIP 174 does not specify a maximum file size, but we set a limit anyway
// to prevent reading a stream indefinitely and running out of memory.
const std::streamsize MAX_FILE_SIZE_PSBT = 100000000; // 100 MiB
const std::streamsize MAX_FILE_SIZE_PSBT = 100000000; // 100 MB
/** A structure for PSBTs which contain per-input information */
struct PSBTInput

View File

@ -777,7 +777,7 @@ static RPCHelpMan getblockfrompeer()
"\nWe must have the header for this block, e.g. using submitheader.\n"
"\nReturns {} if a block-request was successfully scheduled\n",
{
{"block_hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash to try to fetch"},
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash to try to fetch"},
{"peer_id", RPCArg::Type::NUM, RPCArg::Optional::NO, "The peer to fetch it from (see getpeerinfo for peer IDs)"},
},
RPCResult{RPCResult::Type::OBJ, "", "",
@ -794,7 +794,7 @@ static RPCHelpMan getblockfrompeer()
ChainstateManager& chainman = EnsureChainman(node);
PeerManager& peerman = EnsurePeerman(node);
const uint256& block_hash{ParseHashV(request.params[0], "block_hash")};
const uint256& block_hash{ParseHashV(request.params[0], "blockhash")};
const NodeId peer_id{request.params[1].get_int64()};
const CBlockIndex* const index = WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(block_hash););
@ -2696,6 +2696,9 @@ public:
static RPCHelpMan scantxoutset()
{
// scriptPubKey corresponding to mainnet address XcJSEb79KEeNbwMU7eE27aL5dhDwvjgBuH
const std::string EXAMPLE_DESCRIPTOR_RAW = "raw(76a91411b366edfc0a8b66feebae5c2e25a7b6a5d1cf3188ac)#fm24fxxy";
return RPCHelpMan{"scantxoutset",
"\nScans the unspent transaction output set for entries that match certain output descriptors.\n"
"Examples of output descriptors are:\n"
@ -2728,13 +2731,7 @@ static RPCHelpMan scantxoutset()
"[scanobjects,...]"},
},
{
RPCResult{"When action=='abort'", RPCResult::Type::BOOL, "", ""},
RPCResult{"When action=='status' and no scan is in progress", RPCResult::Type::NONE, "", ""},
RPCResult{"When action=='status' and scan is in progress", RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::NUM, "progress", "The scan progress"},
}},
RPCResult{"When action=='start'", RPCResult::Type::OBJ, "", "", {
RPCResult{"when action=='start'; only returns after scan completes", RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::BOOL, "success", "Whether the scan was completed"},
{RPCResult::Type::NUM, "txouts", "The number of unspent transaction outputs scanned"},
{RPCResult::Type::NUM, "height", "The current block height (index)"},
@ -2753,8 +2750,21 @@ static RPCHelpMan scantxoutset()
}},
{RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of all found unspent outputs in " + CURRENCY_UNIT},
}},
RPCResult{"when action=='abort'", RPCResult::Type::BOOL, "success", "True if scan will be aborted (not necessarily before this RPC returns), or false if there is no scan to abort"},
RPCResult{"when action=='status' and a scan is currently in progress", RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::NUM, "progress", "Approximate percent complete"},
}},
RPCResult{"when action=='status' and no scan is in progress - possibly already completed", RPCResult::Type::NONE, "", ""},
},
RPCExamples{
HelpExampleCli("scantxoutset", "start \'[\"" + EXAMPLE_DESCRIPTOR_RAW + "\"]\'") +
HelpExampleCli("scantxoutset", "status") +
HelpExampleCli("scantxoutset", "abort") +
HelpExampleRpc("scantxoutset", "\"start\", [\"" + EXAMPLE_DESCRIPTOR_RAW + "\"]") +
HelpExampleRpc("scantxoutset", "\"status\"") +
HelpExampleRpc("scantxoutset", "\"abort\"")
},
RPCExamples{""},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR});

View File

@ -200,7 +200,7 @@ static bool getScriptFromDescriptor(const std::string& descriptor, CScript& scri
FlatSigningProvider provider;
std::vector<CScript> scripts;
if (!desc->Expand(0, key_provider, scripts, provider)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot derive script without private keys");
}
// Combo descriptors can have 2 or 4 scripts, so we can't just check scripts.size() == 1

View File

@ -443,13 +443,13 @@ static RPCHelpMan deriveaddresses()
FlatSigningProvider provider;
std::vector<CScript> scripts;
if (!desc->Expand(i, key_provider, scripts, provider)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot derive script without private keys");
}
for (const CScript &script : scripts) {
CTxDestination dest;
if (!ExtractDestination(script, dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Descriptor does not have a corresponding address"));
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Descriptor does not have a corresponding address");
}
addresses.push_back(EncodeDestination(dest));

View File

@ -44,8 +44,6 @@ static CService ip(uint32_t i)
return CService(CNetAddr(s), Params().GetDefaultPort());
}
static NodeId id = 0;
void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds);
BOOST_FIXTURE_TEST_SUITE(denialofservice_tests, TestingSetup)
@ -71,6 +69,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
// Mock an outbound peer
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
NodeId id{0};
CNode dummyNode1{id++,
ServiceFlags(NODE_NETWORK),
/*sock=*/nullptr,
@ -127,7 +126,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
peerLogic->FinalizeNode(dummyNode1);
}
static void AddRandomOutboundPeer(std::vector<CNode*>& vNodes, PeerManager& peerLogic, ConnmanTestMsg& connman, ConnectionType connType)
static void AddRandomOutboundPeer(NodeId& id, std::vector<CNode*>& vNodes, PeerManager& peerLogic, ConnmanTestMsg& connman, ConnectionType connType)
{
CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
vNodes.emplace_back(new CNode{id++,
@ -151,6 +150,7 @@ static void AddRandomOutboundPeer(std::vector<CNode*>& vNodes, PeerManager& peer
BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
{
NodeId id{0};
const CChainParams& chainparams = Params();
auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler,
@ -172,7 +172,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
// Mock some outbound peers
for (int i = 0; i < max_outbound_full_relay; ++i) {
AddRandomOutboundPeer(vNodes, *peerLogic, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
}
peerLogic->CheckForStaleTipAndEvictPeers();
@ -198,7 +198,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
// on the next check (since we're mocking the time to be in the future, the
// required time connected check should be satisfied).
SetMockTime(time_init);
AddRandomOutboundPeer(vNodes, *peerLogic, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::OUTBOUND_FULL_RELAY);
SetMockTime(time_later);
peerLogic->CheckForStaleTipAndEvictPeers();
@ -230,6 +230,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
BOOST_AUTO_TEST_CASE(block_relay_only_eviction)
{
NodeId id{0};
const CChainParams& chainparams = Params();
auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr, *m_node.scheduler,
@ -249,7 +250,7 @@ BOOST_AUTO_TEST_CASE(block_relay_only_eviction)
// Add block-relay-only peers up to the limit
for (int i = 0; i < max_outbound_block_relay; ++i) {
AddRandomOutboundPeer(vNodes, *peerLogic, *connman, ConnectionType::BLOCK_RELAY);
AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::BLOCK_RELAY);
}
peerLogic->CheckForStaleTipAndEvictPeers();
@ -258,7 +259,7 @@ BOOST_AUTO_TEST_CASE(block_relay_only_eviction)
}
// Add an extra block-relay-only peer breaking the limit (mocks logic in ThreadOpenConnections)
AddRandomOutboundPeer(vNodes, *peerLogic, *connman, ConnectionType::BLOCK_RELAY);
AddRandomOutboundPeer(id, vNodes, *peerLogic, *connman, ConnectionType::BLOCK_RELAY);
peerLogic->CheckForStaleTipAndEvictPeers();
// The extra peer should only get marked for eviction after MINIMUM_CONNECT_TIME
@ -316,6 +317,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
std::array<CNode*, 3> nodes;
banman->ClearBanned();
NodeId id{0};
nodes[0] = new CNode{id++,
NODE_NETWORK,
/*sock=*/nullptr,
@ -424,6 +426,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
SetMockTime(nStartTime); // Overrides future calls to GetTime()
CAddress addr(ip(0xa0b0c001), NODE_NONE);
NodeId id{0};
CNode dummyNode{id++,
NODE_NETWORK,
/*sock=*/nullptr,

View File

@ -64,7 +64,7 @@ FUZZ_TARGET(netbase_dns_lookup)
}
{
CSubNet resolved_subnet;
if (LookupSubNet(name, resolved_subnet, fuzzed_dns_lookup_function)) {
if (LookupSubNet(name, resolved_subnet)) {
assert(resolved_subnet.IsValid());
}
}

View File

@ -676,10 +676,13 @@ BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
const uint16_t bind_port = 20001;
m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));
const uint32_t current_time = static_cast<uint32_t>(GetAdjustedTime());
SetMockTime(current_time);
// Our address:port as seen from the peer, completely different from the above.
in_addr peer_us_addr;
peer_us_addr.s_addr = htonl(0x02030405);
const CAddress peer_us{CService{peer_us_addr, 20002}, NODE_NETWORK};
const CAddress peer_us{CService{peer_us_addr, 20002}, NODE_NETWORK, current_time};
// Create a peer with a routable IPv4 address (outbound).
in_addr peer_out_in_addr;
@ -700,7 +703,7 @@ BOOST_AUTO_TEST_CASE(get_local_addr_for_peer_port)
// Without the fix peer_us:8333 is chosen instead of the proper peer_us:bind_port.
auto chosen_local_addr = GetLocalAddrForPeer(&peer_out);
BOOST_REQUIRE(chosen_local_addr);
const CService expected{peer_us_addr, bind_port};
const CAddress expected{CService{peer_us_addr, bind_port}, NODE_NETWORK, current_time};
BOOST_CHECK(*chosen_local_addr == expected);
// Create a peer with a routable IPv4 address (inbound).

View File

@ -109,20 +109,21 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
curr_tip = ::g_best_block;
CChainState* background_cs;
BOOST_CHECK_EQUAL(chainman.GetAll().size(), 2);
for (CChainState* cs : chainman.GetAll()) {
if (cs != &chainman.ActiveChainstate()) {
background_cs = cs;
CChainState& background_cs{*[&] {
for (CChainState* cs : chainman.GetAll()) {
if (cs != &chainman.ActiveChainstate()) {
return cs;
}
}
}
BOOST_CHECK(background_cs);
assert(false);
}()};
// Create a block to append to the validation chain.
std::vector<CMutableTransaction> noTxns;
CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
CBlock validation_block = this->CreateBlock(noTxns, scriptPubKey, *background_cs);
CBlock validation_block = this->CreateBlock(noTxns, scriptPubKey, background_cs);
auto pblock = std::make_shared<const CBlock>(validation_block);
BlockValidationState state;
CBlockIndex* pindex = nullptr;
@ -135,15 +136,15 @@ BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
LOCK(::cs_main);
bool checked = CheckBlock(*pblock, state, chainparams.GetConsensus());
BOOST_CHECK(checked);
bool accepted = background_cs->AcceptBlock(
bool accepted = background_cs.AcceptBlock(
pblock, state, &pindex, true, nullptr, &newblock);
BOOST_CHECK(accepted);
}
// UpdateTip is called here
bool block_added = background_cs->ActivateBestChain(state, pblock);
bool block_added = background_cs.ActivateBestChain(state, pblock);
// Ensure tip is as expected
BOOST_CHECK_EQUAL(background_cs->m_chain.Tip()->GetBlockHash(), validation_block.GetHash());
BOOST_CHECK_EQUAL(background_cs.m_chain.Tip()->GetBlockHash(), validation_block.GetHash());
// g_best_block should be unchanged after adding a block to the background
// validation chain.

View File

@ -282,6 +282,7 @@ static void check_computeblockversion(const Consensus::Params& params, Consensus
nStartTime == Consensus::BIP9Deployment::NEVER_ACTIVE)
{
BOOST_CHECK_EQUAL(min_activation_height, 0);
BOOST_CHECK_EQUAL(nTimeout, Consensus::BIP9Deployment::NO_TIMEOUT);
return;
}

View File

@ -1529,6 +1529,11 @@ RPCHelpMan importmulti()
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(mainRequest);
if (!pwallet) return NullUniValue;
CWallet& wallet{*pwallet};
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
wallet.BlockUntilSyncedToCurrentChain();
EnsureLegacyScriptPubKeyMan(*pwallet, true);
@ -1828,6 +1833,11 @@ RPCHelpMan importdescriptors() {
// Acquire the wallet
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(main_request);
if (!pwallet) return NullUniValue;
CWallet& wallet{*pwallet};
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
wallet.BlockUntilSyncedToCurrentChain();
// Make sure wallet is a descriptor wallet
if (!pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {

View File

@ -3694,6 +3694,11 @@ static RPCHelpMan rescanblockchain()
{
std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request);
if (!pwallet) return NullUniValue;
CWallet& wallet{*pwallet};
// Make sure the results are valid at least up to the most recent block
// the user could have gotten from another RPC command prior to now
wallet.BlockUntilSyncedToCurrentChain();
WalletRescanReserver reserver(*pwallet);
if (!reserver.reserve()) {

View File

@ -37,7 +37,7 @@ CLTV_HEIGHT = 1351
# Helper function to modify a transaction by
# 1) prepending a given script to the scriptSig of vin 0 and
# 2) (optionally) modify the nSequence of vin 0 and the tx's nLockTime
def cltv_modify_tx(node, tx, prepend_scriptsig, nsequence=None, nlocktime=None):
def cltv_modify_tx(tx, prepend_scriptsig, nsequence=None, nlocktime=None):
assert_equal(len(tx.vin), 1)
if nsequence is not None:
tx.vin[0].nSequence = nsequence
@ -45,10 +45,9 @@ def cltv_modify_tx(node, tx, prepend_scriptsig, nsequence=None, nlocktime=None):
tx.vin[0].scriptSig = CScript(prepend_scriptsig + list(CScript(tx.vin[0].scriptSig)))
tx.rehash()
return tx
def cltv_invalidate(node, tx, failure_reason):
def cltv_invalidate(tx, failure_reason):
# Modify the signature in vin 0 and nSequence/nLockTime of the tx to fail CLTV
#
# According to BIP65, OP_CHECKLOCKTIMEVERIFY can fail due the following reasons:
@ -69,14 +68,14 @@ def cltv_invalidate(node, tx, failure_reason):
[[CScriptNum(500), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0xffffffff, 500],
][failure_reason]
return cltv_modify_tx(node, tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
cltv_modify_tx(tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
def cltv_validate(node, tx, height):
def cltv_validate(tx, height):
# Modify the signature in vin 0 and nSequence/nLockTime of the tx to pass CLTV
scheme = [[CScriptNum(height), OP_CHECKLOCKTIMEVERIFY, OP_DROP], 0, height]
return cltv_modify_tx(node, tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
cltv_modify_tx(tx, prepend_scriptsig=scheme[0], nsequence=scheme[1], nlocktime=scheme[2])
class BIP65Test(BitcoinTestFramework):
@ -113,17 +112,17 @@ class BIP65Test(BitcoinTestFramework):
self.log.info("Test that invalid-according-to-CLTV transactions can still appear in a block")
# create one invalid tx per CLTV failure reason (5 in total) and collect them
invalid_ctlv_txs = []
invalid_cltv_txs = []
for i in range(5):
spendtx = wallet.create_self_transfer(from_node=self.nodes[0])['tx']
spendtx = cltv_invalidate(self.nodes[0], spendtx, i)
invalid_ctlv_txs.append(spendtx)
cltv_invalidate(spendtx, i)
invalid_cltv_txs.append(spendtx)
tip = self.nodes[0].getbestblockhash()
block_time = self.nodes[0].getblockheader(tip)['mediantime'] + 1
block = create_block(int(tip, 16), create_coinbase(CLTV_HEIGHT - 1), block_time)
block.nVersion = 3
block.vtx.extend(invalid_ctlv_txs)
block.vtx.extend(invalid_cltv_txs)
block.hashMerkleRoot = block.calc_merkle_root()
block.solve()
@ -151,7 +150,7 @@ class BIP65Test(BitcoinTestFramework):
# create and test one invalid tx per CLTV failure reason (5 in total)
for i in range(5):
spendtx = wallet.create_self_transfer(from_node=self.nodes[0])['tx']
spendtx = cltv_invalidate(self.nodes[0], spendtx, i)
cltv_invalidate(spendtx, i)
expected_cltv_reject_reason = [
"non-mandatory-script-verify-flag (Operation not valid with the current stack size)",
@ -176,7 +175,7 @@ class BIP65Test(BitcoinTestFramework):
peer.sync_with_ping()
self.log.info("Test that a version 4 block with a valid-according-to-CLTV transaction is accepted")
spendtx = cltv_validate(self.nodes[0], spendtx, CLTV_HEIGHT - 1)
cltv_validate(spendtx, CLTV_HEIGHT - 1)
block.vtx.pop(1)
block.vtx.append(spendtx)

View File

@ -64,7 +64,6 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[0].generate(1)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
self.nodes[1].syncwithvalidationinterfacequeue() # Sync the timestamp to the wallet, so that importmulti works
node0_address1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
@ -259,7 +258,6 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
self.nodes[1].syncwithvalidationinterfacequeue()
self.log.info("Should import a p2sh")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
@ -280,7 +278,6 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
self.nodes[1].syncwithvalidationinterfacequeue()
self.log.info("Should import a p2sh with respective redeem script")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
@ -301,7 +298,6 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
self.nodes[1].syncwithvalidationinterfacequeue()
self.log.info("Should import a p2sh with respective redeem script and private keys")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
@ -327,7 +323,6 @@ class ImportMultiTest(BitcoinTestFramework):
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
timestamp = self.nodes[1].getblock(self.nodes[1].getbestblockhash())['mediantime']
self.nodes[1].syncwithvalidationinterfacequeue()
self.log.info("Should import a p2sh with respective redeem script and private keys")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},